Merge pull request #225 from mistoll/master
[mono.git] / mcs / class / IKVM.Reflection / GenericWrappers.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 System.Text;
27
28 namespace IKVM.Reflection
29 {
30         // this represents both generic method instantiations and non-generic methods on generic type instantations
31         // (this means that it can be a generic method declaration as well as a generic method instance)
32         sealed class GenericMethodInstance : MethodInfo
33         {
34                 private readonly Type declaringType;
35                 private readonly MethodInfo method;
36                 private readonly Type[] methodArgs;
37                 private MethodSignature lazyMethodSignature;
38
39                 internal GenericMethodInstance(Type declaringType, MethodInfo method, Type[] methodArgs)
40                 {
41                         System.Diagnostics.Debug.Assert(!(method is GenericMethodInstance));
42                         this.declaringType = declaringType;
43                         this.method = method;
44                         this.methodArgs = methodArgs;
45                 }
46
47                 public override bool Equals(object obj)
48                 {
49                         GenericMethodInstance other = obj as GenericMethodInstance;
50                         return other != null
51                                 && other.method.Equals(method)
52                                 && other.declaringType.Equals(declaringType)
53                                 && Util.ArrayEquals(other.methodArgs, methodArgs);
54                 }
55
56                 public override int GetHashCode()
57                 {
58                         return declaringType.GetHashCode() * 33 ^ method.GetHashCode() ^ Util.GetHashCode(methodArgs);
59                 }
60
61                 public override Type ReturnType
62                 {
63                         get { return method.ReturnType.BindTypeParameters(this); }
64                 }
65
66                 public override ParameterInfo ReturnParameter
67                 {
68                         get { return new GenericParameterInfoImpl(this, method.ReturnParameter); }
69                 }
70
71                 public override ParameterInfo[] GetParameters()
72                 {
73                         ParameterInfo[] parameters = method.GetParameters();
74                         for (int i = 0; i < parameters.Length; i++)
75                         {
76                                 parameters[i] = new GenericParameterInfoImpl(this, parameters[i]);
77                         }
78                         return parameters;
79                 }
80
81                 internal override int ParameterCount
82                 {
83                         get { return method.ParameterCount; }
84                 }
85
86                 public override CallingConventions CallingConvention
87                 {
88                         get { return method.CallingConvention; }
89                 }
90
91                 public override MethodAttributes Attributes
92                 {
93                         get { return method.Attributes; }
94                 }
95
96                 public override MethodImplAttributes GetMethodImplementationFlags()
97                 {
98                         return method.GetMethodImplementationFlags();
99                 }
100
101                 public override string Name
102                 {
103                         get { return method.Name; }
104                 }
105
106                 public override Type DeclaringType
107                 {
108                         get { return declaringType.IsModulePseudoType ? null : declaringType; }
109                 }
110
111                 public override Module Module
112                 {
113                         get { return method.Module; }
114                 }
115
116                 public override int MetadataToken
117                 {
118                         get { return method.MetadataToken; }
119                 }
120
121                 public override MethodBody GetMethodBody()
122                 {
123                         IKVM.Reflection.Reader.MethodDefImpl md = method as IKVM.Reflection.Reader.MethodDefImpl;
124                         if (md != null)
125                         {
126                                 return md.GetMethodBody(this);
127                         }
128                         throw new NotSupportedException();
129                 }
130
131                 public override int __MethodRVA
132                 {
133                         get { return method.__MethodRVA; }
134                 }
135
136                 public override MethodInfo MakeGenericMethod(params Type[] typeArguments)
137                 {
138                         return new GenericMethodInstance(declaringType, method, typeArguments);
139                 }
140
141                 public override bool IsGenericMethod
142                 {
143                         get { return method.IsGenericMethod; }
144                 }
145
146                 public override bool IsGenericMethodDefinition
147                 {
148                         get { return method.IsGenericMethodDefinition && methodArgs == null; }
149                 }
150
151                 public override bool ContainsGenericParameters
152                 {
153                         get
154                         {
155                                 if (declaringType.ContainsGenericParameters)
156                                 {
157                                         return true;
158                                 }
159                                 if (methodArgs != null)
160                                 {
161                                         foreach (Type type in methodArgs)
162                                         {
163                                                 if (type.ContainsGenericParameters)
164                                                 {
165                                                         return true;
166                                                 }
167                                         }
168                                 }
169                                 return false;
170                         }
171                 }
172
173                 public override MethodInfo GetGenericMethodDefinition()
174                 {
175                         if (this.IsGenericMethod)
176                         {
177                                 if (this.IsGenericMethodDefinition)
178                                 {
179                                         return this;
180                                 }
181                                 else if (declaringType.IsGenericTypeInstance)
182                                 {
183                                         return new GenericMethodInstance(declaringType, method, null);
184                                 }
185                                 else
186                                 {
187                                         return method;
188                                 }
189                         }
190                         throw new InvalidOperationException();
191                 }
192
193                 public override MethodBase __GetMethodOnTypeDefinition()
194                 {
195                         return method;
196                 }
197
198                 public override Type[] GetGenericArguments()
199                 {
200                         if (methodArgs == null)
201                         {
202                                 return method.GetGenericArguments();
203                         }
204                         else
205                         {
206                                 return (Type[])methodArgs.Clone();
207                         }
208                 }
209
210                 internal override Type GetGenericMethodArgument(int index)
211                 {
212                         if (methodArgs == null)
213                         {
214                                 return method.GetGenericMethodArgument(index);
215                         }
216                         else
217                         {
218                                 return methodArgs[index];
219                         }
220                 }
221
222                 internal override int GetGenericMethodArgumentCount()
223                 {
224                         return method.GetGenericMethodArgumentCount();
225                 }
226
227                 internal override IList<CustomAttributeData> GetCustomAttributesData(Type attributeType)
228                 {
229                         return method.GetCustomAttributesData(attributeType);
230                 }
231
232                 internal override MethodInfo GetMethodOnTypeDefinition()
233                 {
234                         return method.GetMethodOnTypeDefinition();
235                 }
236
237                 internal override int ImportTo(Emit.ModuleBuilder module)
238                 {
239                         if (methodArgs == null)
240                         {
241                                 return module.ImportMethodOrField(declaringType, method.Name, method.MethodSignature);
242                         }
243                         else
244                         {
245                                 Writer.ByteBuffer spec = new Writer.ByteBuffer(10);
246                                 Signature.WriteMethodSpec(module, spec, methodArgs);
247                                 Metadata.MethodSpecTable.Record rec = new Metadata.MethodSpecTable.Record();
248                                 Emit.MethodBuilder mb = method as Emit.MethodBuilder;
249                                 if (mb != null && mb.ModuleBuilder == module && !declaringType.IsGenericType)
250                                 {
251                                         rec.Method = mb.MetadataToken;
252                                 }
253                                 else
254                                 {
255                                         rec.Method = module.ImportMember(GetGenericMethodDefinition());
256                                 }
257                                 rec.Instantiation = module.Blobs.Add(spec);
258                                 return 0x2B000000 | module.MethodSpec.FindOrAddRecord(rec);
259                         }
260                 }
261
262                 internal override MethodSignature MethodSignature
263                 {
264                         get { return lazyMethodSignature ?? (lazyMethodSignature = method.MethodSignature.Bind(declaringType, methodArgs)); }
265                 }
266
267                 internal override MethodBase BindTypeParameters(Type type)
268                 {
269                         System.Diagnostics.Debug.Assert(methodArgs == null);
270                         return new GenericMethodInstance(declaringType.BindTypeParameters(type), method, null);
271                 }
272
273                 internal override bool HasThis
274                 {
275                         get { return method.HasThis; }
276                 }
277         }
278
279         sealed class GenericFieldInstance : FieldInfo
280         {
281                 private readonly Type declaringType;
282                 private readonly FieldInfo field;
283
284                 internal GenericFieldInstance(Type declaringType, FieldInfo field)
285                 {
286                         this.declaringType = declaringType;
287                         this.field = field;
288                 }
289
290                 public override bool Equals(object obj)
291                 {
292                         GenericFieldInstance other = obj as GenericFieldInstance;
293                         return other != null && other.declaringType.Equals(declaringType) && other.field.Equals(field);
294                 }
295
296                 public override int GetHashCode()
297                 {
298                         return declaringType.GetHashCode() * 3 ^ field.GetHashCode();
299                 }
300
301                 public override FieldAttributes Attributes
302                 {
303                         get { return field.Attributes; }
304                 }
305
306                 public override string Name
307                 {
308                         get { return field.Name; }
309                 }
310
311                 public override Type DeclaringType
312                 {
313                         get { return declaringType; }
314                 }
315
316                 public override Module Module
317                 {
318                         get { return declaringType.Module; }
319                 }
320
321                 public override int MetadataToken
322                 {
323                         get { return field.MetadataToken; }
324                 }
325
326                 public override object GetRawConstantValue()
327                 {
328                         return field.GetRawConstantValue();
329                 }
330
331                 public override void __GetDataFromRVA(byte[] data, int offset, int length)
332                 {
333                         field.__GetDataFromRVA(data, offset, length);
334                 }
335
336                 public override int __FieldRVA
337                 {
338                         get { return field.__FieldRVA; }
339                 }
340
341                 public override FieldInfo __GetFieldOnTypeDefinition()
342                 {
343                         return field;
344                 }
345
346                 internal override IList<CustomAttributeData> GetCustomAttributesData(Type attributeType)
347                 {
348                         return field.GetCustomAttributesData(attributeType);
349                 }
350
351                 internal override FieldSignature FieldSignature
352                 {
353                         get { return field.FieldSignature.ExpandTypeParameters(declaringType); }
354                 }
355
356                 internal override int ImportTo(Emit.ModuleBuilder module)
357                 {
358                         return module.ImportMethodOrField(declaringType, field.Name, field.FieldSignature);
359                 }
360
361                 internal override FieldInfo BindTypeParameters(Type type)
362                 {
363                         return new GenericFieldInstance(declaringType.BindTypeParameters(type), field);
364                 }
365         }
366
367         sealed class GenericParameterInfoImpl : ParameterInfo
368         {
369                 private readonly GenericMethodInstance method;
370                 private readonly ParameterInfo parameterInfo;
371
372                 internal GenericParameterInfoImpl(GenericMethodInstance method, ParameterInfo parameterInfo)
373                 {
374                         this.method = method;
375                         this.parameterInfo = parameterInfo;
376                 }
377
378                 public override string Name
379                 {
380                         get { return parameterInfo.Name; }
381                 }
382
383                 public override Type ParameterType
384                 {
385                         get { return parameterInfo.ParameterType.BindTypeParameters(method); }
386                 }
387
388                 public override ParameterAttributes Attributes
389                 {
390                         get { return parameterInfo.Attributes; }
391                 }
392
393                 public override int Position
394                 {
395                         get { return parameterInfo.Position; }
396                 }
397
398                 public override object RawDefaultValue
399                 {
400                         get { return parameterInfo.RawDefaultValue; }
401                 }
402
403                 public override CustomModifiers __GetCustomModifiers()
404                 {
405                         return parameterInfo.__GetCustomModifiers().Bind(method);
406                 }
407
408                 public override MemberInfo Member
409                 {
410                         get { return method; }
411                 }
412
413                 public override int MetadataToken
414                 {
415                         get { return parameterInfo.MetadataToken; }
416                 }
417
418                 internal override Module Module
419                 {
420                         get { return method.Module; }
421                 }
422         }
423
424         sealed class GenericPropertyInfo : PropertyInfo
425         {
426                 private readonly Type typeInstance;
427                 private readonly PropertyInfo property;
428
429                 internal GenericPropertyInfo(Type typeInstance, PropertyInfo property)
430                 {
431                         this.typeInstance = typeInstance;
432                         this.property = property;
433                 }
434
435                 public override bool Equals(object obj)
436                 {
437                         GenericPropertyInfo other = obj as GenericPropertyInfo;
438                         return other != null && other.typeInstance == typeInstance && other.property == property;
439                 }
440
441                 public override int GetHashCode()
442                 {
443                         return typeInstance.GetHashCode() * 537 + property.GetHashCode();
444                 }
445
446                 public override PropertyAttributes Attributes
447                 {
448                         get { return property.Attributes; }
449                 }
450
451                 public override bool CanRead
452                 {
453                         get { return property.CanRead; }
454                 }
455
456                 public override bool CanWrite
457                 {
458                         get { return property.CanWrite; }
459                 }
460
461                 private MethodInfo Wrap(MethodInfo method)
462                 {
463                         if (method == null)
464                         {
465                                 return null;
466                         }
467                         return new GenericMethodInstance(typeInstance, method, null);
468                 }
469
470                 public override MethodInfo GetGetMethod(bool nonPublic)
471                 {
472                         return Wrap(property.GetGetMethod(nonPublic));
473                 }
474
475                 public override MethodInfo GetSetMethod(bool nonPublic)
476                 {
477                         return Wrap(property.GetSetMethod(nonPublic));
478                 }
479
480                 public override MethodInfo[] GetAccessors(bool nonPublic)
481                 {
482                         MethodInfo[] accessors = property.GetAccessors(nonPublic);
483                         for (int i = 0; i < accessors.Length; i++)
484                         {
485                                 accessors[i] = Wrap(accessors[i]);
486                         }
487                         return accessors;
488                 }
489
490                 public override object GetRawConstantValue()
491                 {
492                         return property.GetRawConstantValue();
493                 }
494
495                 internal override bool IsPublic
496                 {
497                         get { return property.IsPublic; }
498                 }
499
500                 internal override bool IsStatic
501                 {
502                         get { return property.IsStatic; }
503                 }
504
505                 internal override PropertySignature PropertySignature
506                 {
507                         get { return property.PropertySignature.ExpandTypeParameters(typeInstance); }
508                 }
509
510                 public override string Name
511                 {
512                         get { return property.Name; }
513                 }
514
515                 public override Type DeclaringType
516                 {
517                         get { return typeInstance; }
518                 }
519
520                 public override Module Module
521                 {
522                         get { return typeInstance.Module; }
523                 }
524
525                 public override int MetadataToken
526                 {
527                         get { return property.MetadataToken; }
528                 }
529
530                 internal override IList<CustomAttributeData> GetCustomAttributesData(Type attributeType)
531                 {
532                         return property.GetCustomAttributesData(attributeType);
533                 }
534
535                 internal override PropertyInfo BindTypeParameters(Type type)
536                 {
537                         return new GenericPropertyInfo(typeInstance.BindTypeParameters(type), property);
538                 }
539         }
540
541         sealed class GenericEventInfo : EventInfo
542         {
543                 private readonly Type typeInstance;
544                 private readonly EventInfo eventInfo;
545
546                 internal GenericEventInfo(Type typeInstance, EventInfo eventInfo)
547                 {
548                         this.typeInstance = typeInstance;
549                         this.eventInfo = eventInfo;
550                 }
551
552                 public override bool Equals(object obj)
553                 {
554                         GenericEventInfo other = obj as GenericEventInfo;
555                         return other != null && other.typeInstance == typeInstance && other.eventInfo == eventInfo;
556                 }
557
558                 public override int GetHashCode()
559                 {
560                         return typeInstance.GetHashCode() * 777 + eventInfo.GetHashCode();
561                 }
562
563                 public override EventAttributes Attributes
564                 {
565                         get { return eventInfo.Attributes; }
566                 }
567
568                 private MethodInfo Wrap(MethodInfo method)
569                 {
570                         if (method == null)
571                         {
572                                 return null;
573                         }
574                         return new GenericMethodInstance(typeInstance, method, null);
575                 }
576
577                 public override MethodInfo GetAddMethod(bool nonPublic)
578                 {
579                         return Wrap(eventInfo.GetAddMethod(nonPublic));
580                 }
581
582                 public override MethodInfo GetRaiseMethod(bool nonPublic)
583                 {
584                         return Wrap(eventInfo.GetRaiseMethod(nonPublic));
585                 }
586
587                 public override MethodInfo GetRemoveMethod(bool nonPublic)
588                 {
589                         return Wrap(eventInfo.GetRemoveMethod(nonPublic));
590                 }
591
592                 public override MethodInfo[] GetOtherMethods(bool nonPublic)
593                 {
594                         MethodInfo[] others = eventInfo.GetOtherMethods(nonPublic);
595                         for (int i = 0; i < others.Length; i++)
596                         {
597                                 others[i] = Wrap(others[i]);
598                         }
599                         return others;
600                 }
601
602                 public override MethodInfo[] __GetMethods()
603                 {
604                         MethodInfo[] others = eventInfo.__GetMethods();
605                         for (int i = 0; i < others.Length; i++)
606                         {
607                                 others[i] = Wrap(others[i]);
608                         }
609                         return others;
610                 }
611
612                 public override Type EventHandlerType
613                 {
614                         get { return eventInfo.EventHandlerType.BindTypeParameters(typeInstance); }
615                 }
616
617                 public override string Name
618                 {
619                         get { return eventInfo.Name; }
620                 }
621
622                 public override Type DeclaringType
623                 {
624                         get { return typeInstance; }
625                 }
626
627                 public override Module Module
628                 {
629                         get { return eventInfo.Module; }
630                 }
631
632                 public override int MetadataToken
633                 {
634                         get { return eventInfo.MetadataToken; }
635                 }
636
637                 internal override IList<CustomAttributeData> GetCustomAttributesData(Type attributeType)
638                 {
639                         return eventInfo.GetCustomAttributesData(attributeType);
640                 }
641
642                 internal override EventInfo BindTypeParameters(Type type)
643                 {
644                         return new GenericEventInfo(typeInstance.BindTypeParameters(type), eventInfo);
645                 }
646
647                 internal override bool IsPublic
648                 {
649                         get { return eventInfo.IsPublic; }
650                 }
651
652                 internal override bool IsStatic
653                 {
654                         get { return eventInfo.IsStatic; }
655                 }
656         }
657 }