Update mcs/class/Commons.Xml.Relaxng/Commons.Xml.Relaxng/RelaxngPattern.cs
[mono.git] / mcs / class / IKVM.Reflection / Reader / TypeDefImpl.cs
1 /*
2   Copyright (C) 2009-2011 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 System.Text;
27 using System.Runtime.InteropServices;
28 using IKVM.Reflection.Metadata;
29
30 namespace IKVM.Reflection.Reader
31 {
32         sealed class TypeDefImpl : Type
33         {
34                 private readonly ModuleReader module;
35                 private readonly int index;
36                 private readonly string typeName;
37                 private readonly string typeNamespace;
38                 private Type[] typeArgs;
39
40                 internal TypeDefImpl(ModuleReader module, int index)
41                 {
42                         this.module = module;
43                         this.index = index;
44                         this.typeName = module.GetString(module.TypeDef.records[index].TypeName);
45                         this.typeNamespace = module.GetString(module.TypeDef.records[index].TypeNamespace);
46                         MarkEnumOrValueType(typeNamespace, typeName);
47                 }
48
49                 public override Type BaseType
50                 {
51                         get
52                         {
53                                 int extends = module.TypeDef.records[index].Extends;
54                                 if ((extends & 0xFFFFFF) == 0)
55                                 {
56                                         return null;
57                                 }
58                                 return module.ResolveType(extends, this);
59                         }
60                 }
61
62                 public override TypeAttributes Attributes
63                 {
64                         get { return (TypeAttributes)module.TypeDef.records[index].Flags; }
65                 }
66
67                 public override EventInfo[] __GetDeclaredEvents()
68                 {
69                         foreach (int i in module.EventMap.Filter(this.MetadataToken))
70                         {
71                                 int evt = module.EventMap.records[i].EventList - 1;
72                                 int end = module.EventMap.records.Length > i + 1 ? module.EventMap.records[i + 1].EventList - 1 : module.Event.records.Length;
73                                 EventInfo[] events = new EventInfo[end - evt];
74                                 if (module.EventPtr.RowCount == 0)
75                                 {
76                                         for (int j = 0; evt < end; evt++, j++)
77                                         {
78                                                 events[j] = new EventInfoImpl(module, this, evt);
79                                         }
80                                 }
81                                 else
82                                 {
83                                         for (int j = 0; evt < end; evt++, j++)
84                                         {
85                                                 events[j] = new EventInfoImpl(module, this, module.EventPtr.records[evt] - 1);
86                                         }
87                                 }
88                                 return events;
89                         }
90                         return Empty<EventInfo>.Array;
91                 }
92
93                 public override FieldInfo[] __GetDeclaredFields()
94                 {
95                         int field = module.TypeDef.records[index].FieldList - 1;
96                         int end = module.TypeDef.records.Length > index + 1 ? module.TypeDef.records[index + 1].FieldList - 1 : module.Field.records.Length;
97                         FieldInfo[] fields = new FieldInfo[end - field];
98                         if (module.FieldPtr.RowCount == 0)
99                         {
100                                 for (int i = 0; field < end; i++, field++)
101                                 {
102                                         fields[i] = module.GetFieldAt(this, field);
103                                 }
104                         }
105                         else
106                         {
107                                 for (int i = 0; field < end; i++, field++)
108                                 {
109                                         fields[i] = module.GetFieldAt(this, module.FieldPtr.records[field] - 1);
110                                 }
111                         }
112                         return fields;
113                 }
114
115                 public override Type[] __GetDeclaredInterfaces()
116                 {
117                         List<Type> list = null;
118                         foreach (int i in module.InterfaceImpl.Filter(this.MetadataToken))
119                         {
120                                 if (list == null)
121                                 {
122                                         list = new List<Type>();
123                                 }
124                                 list.Add(module.ResolveType(module.InterfaceImpl.records[i].Interface, this));
125                         }
126                         return Util.ToArray(list, Type.EmptyTypes);
127                 }
128
129                 public override MethodBase[] __GetDeclaredMethods()
130                 {
131                         int method = module.TypeDef.records[index].MethodList - 1;
132                         int end = module.TypeDef.records.Length > index + 1 ? module.TypeDef.records[index + 1].MethodList - 1 : module.MethodDef.records.Length;
133                         MethodBase[] methods = new MethodBase[end - method];
134                         if (module.MethodPtr.RowCount == 0)
135                         {
136                                 for (int i = 0; method < end; method++, i++)
137                                 {
138                                         methods[i] = module.GetMethodAt(this, method);
139                                 }
140                         }
141                         else
142                         {
143                                 for (int i = 0; method < end; method++, i++)
144                                 {
145                                         methods[i] = module.GetMethodAt(this, module.MethodPtr.records[method] - 1);
146                                 }
147                         }
148                         return methods;
149                 }
150
151                 public override __MethodImplMap __GetMethodImplMap()
152                 {
153                         PopulateGenericArguments();
154                         List<MethodInfo> bodies = new List<MethodInfo>();
155                         List<List<MethodInfo>> declarations = new List<List<MethodInfo>>();
156                         foreach (int i in module.MethodImpl.Filter(this.MetadataToken))
157                         {
158                                 MethodInfo body = (MethodInfo)module.ResolveMethod(module.MethodImpl.records[i].MethodBody, typeArgs, null);
159                                 int index = bodies.IndexOf(body);
160                                 if (index == -1)
161                                 {
162                                         index = bodies.Count;
163                                         bodies.Add(body);
164                                         declarations.Add(new List<MethodInfo>());
165                                 }
166                                 MethodInfo declaration = (MethodInfo)module.ResolveMethod(module.MethodImpl.records[i].MethodDeclaration, typeArgs, null);
167                                 declarations[index].Add(declaration);
168                         }
169                         __MethodImplMap map = new __MethodImplMap();
170                         map.TargetType = this;
171                         map.MethodBodies = bodies.ToArray();
172                         map.MethodDeclarations = new MethodInfo[declarations.Count][];
173                         for (int i = 0; i < map.MethodDeclarations.Length; i++)
174                         {
175                                 map.MethodDeclarations[i] = declarations[i].ToArray();
176                         }
177                         return map;
178                 }
179
180                 public override Type[] __GetDeclaredTypes()
181                 {
182                         int token = this.MetadataToken;
183                         List<Type> list = new List<Type>();
184                         // note that the NestedClass table is sorted on NestedClass, so we can't use binary search
185                         for (int i = 0; i < module.NestedClass.records.Length; i++)
186                         {
187                                 if (module.NestedClass.records[i].EnclosingClass == token)
188                                 {
189                                         list.Add(module.ResolveType(module.NestedClass.records[i].NestedClass));
190                                 }
191                         }
192                         return list.ToArray();
193                 }
194
195                 public override PropertyInfo[] __GetDeclaredProperties()
196                 {
197                         foreach (int i in module.PropertyMap.Filter(this.MetadataToken))
198                         {
199                                 int property = module.PropertyMap.records[i].PropertyList - 1;
200                                 int end = module.PropertyMap.records.Length > i + 1 ? module.PropertyMap.records[i + 1].PropertyList - 1 : module.Property.records.Length;
201                                 PropertyInfo[] properties = new PropertyInfo[end - property];
202                                 if (module.PropertyPtr.RowCount == 0)
203                                 {
204                                         for (int j = 0; property < end; property++, j++)
205                                         {
206                                                 properties[j] = new PropertyInfoImpl(module, this, property);
207                                         }
208                                 }
209                                 else
210                                 {
211                                         for (int j = 0; property < end; property++, j++)
212                                         {
213                                                 properties[j] = new PropertyInfoImpl(module, this, module.PropertyPtr.records[property] - 1);
214                                         }
215                                 }
216                                 return properties;
217                         }
218                         return Empty<PropertyInfo>.Array;
219                 }
220
221                 public override string __Name
222                 {
223                         get { return typeName; }
224                 }
225
226                 public override string __Namespace
227                 {
228                         get { return typeNamespace; }
229                 }
230
231                 public override string Name
232                 {
233                         get { return TypeNameParser.Escape(typeName); }
234                 }
235
236                 public override string FullName
237                 {
238                         get { return GetFullName(); }
239                 }
240
241                 public override int MetadataToken
242                 {
243                         get { return (TypeDefTable.Index << 24) + index + 1; }
244                 }
245
246                 public override Type[] GetGenericArguments()
247                 {
248                         PopulateGenericArguments();
249                         return Util.Copy(typeArgs);
250                 }
251
252                 private void PopulateGenericArguments()
253                 {
254                         if (typeArgs == null)
255                         {
256                                 int token = this.MetadataToken;
257                                 int first = module.GenericParam.FindFirstByOwner(token);
258                                 if (first == -1)
259                                 {
260                                         typeArgs = Type.EmptyTypes;
261                                 }
262                                 else
263                                 {
264                                         List<Type> list = new List<Type>();
265                                         int len = module.GenericParam.records.Length;
266                                         for (int i = first; i < len && module.GenericParam.records[i].Owner == token; i++)
267                                         {
268                                                 list.Add(new GenericTypeParameter(module, i));
269                                         }
270                                         typeArgs = list.ToArray();
271                                 }
272                         }
273                 }
274
275                 internal override Type GetGenericTypeArgument(int index)
276                 {
277                         PopulateGenericArguments();
278                         return typeArgs[index];
279                 }
280
281                 public override CustomModifiers[] __GetGenericArgumentsCustomModifiers()
282                 {
283                         PopulateGenericArguments();
284                         return new CustomModifiers[typeArgs.Length];
285                 }
286
287                 public override bool IsGenericType
288                 {
289                         get { return IsGenericTypeDefinition; }
290                 }
291
292                 public override bool IsGenericTypeDefinition
293                 {
294                         get { return module.GenericParam.FindFirstByOwner(this.MetadataToken) != -1; }
295                 }
296
297                 public override Type GetGenericTypeDefinition()
298                 {
299                         if (IsGenericTypeDefinition)
300                         {
301                                 return this;
302                         }
303                         throw new InvalidOperationException();
304                 }
305
306                 public override string ToString()
307                 {
308                         StringBuilder sb = new StringBuilder(this.FullName);
309                         string sep = "[";
310                         foreach (Type arg in GetGenericArguments())
311                         {
312                                 sb.Append(sep);
313                                 sb.Append(arg);
314                                 sep = ",";
315                         }
316                         if (sep != "[")
317                         {
318                                 sb.Append(']');
319                         }
320                         return sb.ToString();
321                 }
322
323                 internal bool IsNestedByFlags
324                 {
325                         get { return (this.Attributes & TypeAttributes.VisibilityMask & ~TypeAttributes.Public) != 0; }
326                 }
327
328                 public override Type DeclaringType
329                 {
330                         get
331                         {
332                                 // note that we cannot use Type.IsNested for this, because that calls DeclaringType
333                                 if (!IsNestedByFlags)
334                                 {
335                                         return null;
336                                 }
337                                 foreach (int i in module.NestedClass.Filter(this.MetadataToken))
338                                 {
339                                         return module.ResolveType(module.NestedClass.records[i].EnclosingClass, null, null);
340                                 }
341                                 throw new InvalidOperationException();
342                         }
343                 }
344
345                 public override StructLayoutAttribute StructLayoutAttribute
346                 {
347                         get
348                         {
349                                 StructLayoutAttribute layout;
350                                 switch (this.Attributes & TypeAttributes.LayoutMask)
351                                 {
352                                         case TypeAttributes.AutoLayout:
353                                                 layout = new StructLayoutAttribute(LayoutKind.Auto);
354                                                 break;
355                                         case TypeAttributes.SequentialLayout:
356                                                 layout = new StructLayoutAttribute(LayoutKind.Sequential);
357                                                 break;
358                                         case TypeAttributes.ExplicitLayout:
359                                                 layout = new StructLayoutAttribute(LayoutKind.Explicit);
360                                                 break;
361                                         default:
362                                                 throw new BadImageFormatException();
363                                 }
364                                 switch (this.Attributes & TypeAttributes.StringFormatMask)
365                                 {
366                                         case TypeAttributes.AnsiClass:
367                                                 layout.CharSet = CharSet.Ansi;
368                                                 break;
369                                         case TypeAttributes.UnicodeClass:
370                                                 layout.CharSet = CharSet.Unicode;
371                                                 break;
372                                         case TypeAttributes.AutoClass:
373                                                 layout.CharSet = CharSet.Auto;
374                                                 break;
375                                         default:
376                                                 layout.CharSet = CharSet.None;
377                                                 break;
378                                 }
379                                 if (!__GetLayout(out layout.Pack, out layout.Size))
380                                 {
381                                         // compatibility with System.Reflection
382                                         layout.Pack = 8;
383                                 }
384                                 return layout;
385                         }
386                 }
387
388                 public override bool __GetLayout(out int packingSize, out int typeSize)
389                 {
390                         foreach (int i in module.ClassLayout.Filter(this.MetadataToken))
391                         {
392                                 packingSize = module.ClassLayout.records[i].PackingSize;
393                                 typeSize = module.ClassLayout.records[i].ClassSize;
394                                 return true;
395                         }
396                         packingSize = 0;
397                         typeSize = 0;
398                         return false;
399                 }
400
401                 public override Module Module
402                 {
403                         get { return module; }
404                 }
405
406                 internal override bool IsModulePseudoType
407                 {
408                         get { return index == 0; }
409                 }
410
411                 internal override IList<CustomAttributeData> GetInterfaceImplCustomAttributes(Type interfaceType, Type attributeType)
412                 {
413                         foreach (int i in module.InterfaceImpl.Filter(this.MetadataToken))
414                         {
415                                 if (module.ResolveType(module.InterfaceImpl.records[i].Interface, this) == interfaceType)
416                                 {
417                                         return module.GetCustomAttributes((InterfaceImplTable.Index << 24) | (i + 1), attributeType);
418                                 }
419                         }
420                         return Empty<CustomAttributeData>.Array;
421                 }
422         }
423 }