do not check order sequence if option /order was not used
[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 : TypeInfo
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
295                         {
296                                 if ((typeFlags & (TypeFlags.IsGenericTypeDefinition | TypeFlags.NotGenericTypeDefinition)) == 0)
297                                 {
298                                         typeFlags |= module.GenericParam.FindFirstByOwner(this.MetadataToken) == -1
299                                                 ? TypeFlags.NotGenericTypeDefinition
300                                                 : TypeFlags.IsGenericTypeDefinition;
301                                 }
302                                 return (typeFlags & TypeFlags.IsGenericTypeDefinition) != 0;
303                         }
304                 }
305
306                 public override Type GetGenericTypeDefinition()
307                 {
308                         if (IsGenericTypeDefinition)
309                         {
310                                 return this;
311                         }
312                         throw new InvalidOperationException();
313                 }
314
315                 public override string ToString()
316                 {
317                         StringBuilder sb = new StringBuilder(this.FullName);
318                         string sep = "[";
319                         foreach (Type arg in GetGenericArguments())
320                         {
321                                 sb.Append(sep);
322                                 sb.Append(arg);
323                                 sep = ",";
324                         }
325                         if (sep != "[")
326                         {
327                                 sb.Append(']');
328                         }
329                         return sb.ToString();
330                 }
331
332                 internal bool IsNestedByFlags
333                 {
334                         get { return (this.Attributes & TypeAttributes.VisibilityMask & ~TypeAttributes.Public) != 0; }
335                 }
336
337                 public override Type DeclaringType
338                 {
339                         get
340                         {
341                                 // note that we cannot use Type.IsNested for this, because that calls DeclaringType
342                                 if (!IsNestedByFlags)
343                                 {
344                                         return null;
345                                 }
346                                 foreach (int i in module.NestedClass.Filter(this.MetadataToken))
347                                 {
348                                         return module.ResolveType(module.NestedClass.records[i].EnclosingClass, null, null);
349                                 }
350                                 throw new InvalidOperationException();
351                         }
352                 }
353
354                 public override StructLayoutAttribute StructLayoutAttribute
355                 {
356                         get
357                         {
358                                 StructLayoutAttribute layout;
359                                 switch (this.Attributes & TypeAttributes.LayoutMask)
360                                 {
361                                         case TypeAttributes.AutoLayout:
362                                                 layout = new StructLayoutAttribute(LayoutKind.Auto);
363                                                 break;
364                                         case TypeAttributes.SequentialLayout:
365                                                 layout = new StructLayoutAttribute(LayoutKind.Sequential);
366                                                 break;
367                                         case TypeAttributes.ExplicitLayout:
368                                                 layout = new StructLayoutAttribute(LayoutKind.Explicit);
369                                                 break;
370                                         default:
371                                                 throw new BadImageFormatException();
372                                 }
373                                 switch (this.Attributes & TypeAttributes.StringFormatMask)
374                                 {
375                                         case TypeAttributes.AnsiClass:
376                                                 layout.CharSet = CharSet.Ansi;
377                                                 break;
378                                         case TypeAttributes.UnicodeClass:
379                                                 layout.CharSet = CharSet.Unicode;
380                                                 break;
381                                         case TypeAttributes.AutoClass:
382                                                 layout.CharSet = CharSet.Auto;
383                                                 break;
384                                         default:
385                                                 layout.CharSet = CharSet.None;
386                                                 break;
387                                 }
388                                 if (!__GetLayout(out layout.Pack, out layout.Size))
389                                 {
390                                         // compatibility with System.Reflection
391                                         layout.Pack = 8;
392                                 }
393                                 return layout;
394                         }
395                 }
396
397                 public override bool __GetLayout(out int packingSize, out int typeSize)
398                 {
399                         foreach (int i in module.ClassLayout.Filter(this.MetadataToken))
400                         {
401                                 packingSize = module.ClassLayout.records[i].PackingSize;
402                                 typeSize = module.ClassLayout.records[i].ClassSize;
403                                 return true;
404                         }
405                         packingSize = 0;
406                         typeSize = 0;
407                         return false;
408                 }
409
410                 public override Module Module
411                 {
412                         get { return module; }
413                 }
414
415                 internal override bool IsModulePseudoType
416                 {
417                         get { return index == 0; }
418                 }
419
420                 internal override bool IsBaked
421                 {
422                         get { return true; }
423                 }
424         }
425 }