[corlib] Peek to attribute import from reference souces
[mono.git] / mcs / class / corlib / System.Reflection / MonoMethod.cs
1 //
2 // MonoMethod.cs: The class used to represent methods from the mono runtime.
3 //
4 // Authors:
5 //   Paolo Molaro (lupus@ximian.com)
6 //   Marek Safar (marek.safar@gmail.com)
7 //
8 // (C) 2001 Ximian, Inc.  http://www.ximian.com
9 // Copyright (C) 2004-2005 Novell, Inc (http://www.novell.com)
10 // Copyright (C) 2012 Xamarin Inc (http://www.xamarin.com)
11 //
12 // Permission is hereby granted, free of charge, to any person obtaining
13 // a copy of this software and associated documentation files (the
14 // "Software"), to deal in the Software without restriction, including
15 // without limitation the rights to use, copy, modify, merge, publish,
16 // distribute, sublicense, and/or sell copies of the Software, and to
17 // permit persons to whom the Software is furnished to do so, subject to
18 // the following conditions:
19 // 
20 // The above copyright notice and this permission notice shall be
21 // included in all copies or substantial portions of the Software.
22 // 
23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
27 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
28 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
29 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30 //
31
32 using System.Collections.Generic;
33 using System.Globalization;
34 using System.Runtime.CompilerServices;
35 using System.Runtime.InteropServices;
36 using System.Runtime.Serialization;
37 #if !FULL_AOT_RUNTIME
38 using System.Reflection.Emit;
39 #endif
40 using System.Security;
41 using System.Threading;
42 using System.Text;
43 using System.Diagnostics;
44
45 namespace System.Reflection {
46         
47         internal struct MonoMethodInfo 
48         {
49 #pragma warning disable 649     
50                 private Type parent;
51                 private Type ret;
52                 internal MethodAttributes attrs;
53                 internal MethodImplAttributes iattrs;
54                 private CallingConventions callconv;
55 #pragma warning restore 649             
56
57                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
58                 static extern void get_method_info (IntPtr handle, out MonoMethodInfo info);
59                 
60                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
61                 static extern int get_method_attributes (IntPtr handle);
62                 
63                 internal static MonoMethodInfo GetMethodInfo (IntPtr handle)
64                 {
65                         MonoMethodInfo info;
66                         MonoMethodInfo.get_method_info (handle, out info);
67                         return info;
68                 }
69
70                 internal static Type GetDeclaringType (IntPtr handle)
71                 {
72                         return GetMethodInfo (handle).parent;
73                 }
74
75                 internal static Type GetReturnType (IntPtr handle)
76                 {
77                         return GetMethodInfo (handle).ret;
78                 }
79
80                 internal static MethodAttributes GetAttributes (IntPtr handle)
81                 {
82                         return (MethodAttributes)get_method_attributes (handle);
83                 }
84
85                 internal static CallingConventions GetCallingConvention (IntPtr handle)
86                 {
87                         return GetMethodInfo (handle).callconv;
88                 }
89
90                 internal static MethodImplAttributes GetMethodImplementationFlags (IntPtr handle)
91                 {
92                         return GetMethodInfo (handle).iattrs;
93                 }
94
95                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
96                 static extern ParameterInfo[] get_parameter_info (IntPtr handle, MemberInfo member);
97
98                 static internal ParameterInfo[] GetParametersInfo (IntPtr handle, MemberInfo member)
99                 {
100                         return get_parameter_info (handle, member);
101                 }
102
103                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
104                 static extern MarshalAsAttribute get_retval_marshal (IntPtr handle);
105
106                 static internal ParameterInfo GetReturnParameterInfo (MonoMethod method)
107                 {
108                         return ParameterInfo.New (GetReturnType (method.mhandle), method, get_retval_marshal (method.mhandle));
109                 }
110         };
111         
112         abstract class RuntimeMethodInfo : MethodInfo
113         {
114         }
115
116         /*
117          * Note: most of this class needs to be duplicated for the contructor, since
118          * the .NET reflection class hierarchy is so broken.
119          */
120         [Serializable()]
121         [StructLayout (LayoutKind.Sequential)]
122         internal class MonoMethod : RuntimeMethodInfo, ISerializable
123         {
124 #pragma warning disable 649
125                 internal IntPtr mhandle;
126                 string name;
127                 Type reftype;
128 #pragma warning restore 649
129
130                 internal MonoMethod () {
131                 }
132
133                 internal MonoMethod (RuntimeMethodHandle mhandle) {
134                         this.mhandle = mhandle.Value;
135                 }
136                 
137                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
138                 internal static extern string get_name (MethodBase method);
139
140                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
141                 internal static extern MonoMethod get_base_method (MonoMethod method, bool definition);
142
143                 public override MethodInfo GetBaseDefinition ()
144                 {
145                         return get_base_method (this, true);
146                 }
147
148                 internal override MethodInfo GetBaseMethod ()
149                 {
150                         return get_base_method (this, false);
151                 }
152
153                 public override ParameterInfo ReturnParameter {
154                         get {
155                                 return MonoMethodInfo.GetReturnParameterInfo (this);
156                         }
157                 }
158
159                 public override Type ReturnType {
160                         get {
161                                 return MonoMethodInfo.GetReturnType (mhandle);
162                         }
163                 }
164                 public override ICustomAttributeProvider ReturnTypeCustomAttributes { 
165                         get {
166                                 return MonoMethodInfo.GetReturnParameterInfo (this);
167                         }
168                 }
169                 
170                 public override MethodImplAttributes GetMethodImplementationFlags ()
171                 {
172                         return MonoMethodInfo.GetMethodImplementationFlags (mhandle);
173                 }
174
175                 public override ParameterInfo[] GetParameters ()
176                 {
177                         var src = MonoMethodInfo.GetParametersInfo (mhandle, this);
178                         if (src.Length == 0)
179                                 return src;
180
181                         // Have to clone because GetParametersInfo icall returns cached value
182                         var dest = new ParameterInfo [src.Length];
183                         Array.FastCopy (src, 0, dest, 0, src.Length);
184                         return dest;
185                 }
186
187                 internal override ParameterInfo[] GetParametersInternal ()
188                 {
189                         return MonoMethodInfo.GetParametersInfo (mhandle, this);
190                 }
191                 
192                 internal override int GetParametersCount ()
193                 {
194                         return MonoMethodInfo.GetParametersInfo (mhandle, this).Length;
195                 }
196
197                 /*
198                  * InternalInvoke() receives the parameters correctly converted by the 
199                  * binder to match the types of the method signature.
200                  */
201                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
202                 internal extern Object InternalInvoke (Object obj, Object[] parameters, out Exception exc);
203
204                 [DebuggerHidden]
205                 [DebuggerStepThrough]
206                 public override Object Invoke (Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture) 
207                 {
208                         if (binder == null)
209                                 binder = Type.DefaultBinder;
210
211                         /*Avoid allocating an array every time*/
212                         ParameterInfo[] pinfo = GetParametersInternal ();
213                         ConvertValues (binder, parameters, pinfo, culture, invokeAttr);
214
215 #if !NET_2_1
216                         if (SecurityManager.SecurityEnabled) {
217                                 // sadly Attributes doesn't tell us which kind of security action this is so
218                                 // we must do it the hard way - and it also means that we can skip calling
219                                 // Attribute (which is another an icall)
220                                 SecurityManager.ReflectedLinkDemandInvoke (this);
221                         }
222 #endif
223
224                         if (ContainsGenericParameters)
225                                 throw new InvalidOperationException ("Late bound operations cannot be performed on types or methods for which ContainsGenericParameters is true.");
226
227                         Exception exc;
228                         object o = null;
229
230                         try {
231                                 // The ex argument is used to distinguish exceptions thrown by the icall
232                                 // from the exceptions thrown by the called method (which need to be
233                                 // wrapped in TargetInvocationException).
234                                 o = InternalInvoke (obj, parameters, out exc);
235                         } catch (ThreadAbortException) {
236                                 throw;
237 #if NET_2_1
238                         } catch (MethodAccessException) {
239                                 throw;
240 #endif
241                         } catch (Exception e) {
242                                 throw new TargetInvocationException (e);
243                         }
244
245                         if (exc != null)
246                                 throw exc;
247                         return o;
248                 }
249
250                 internal static void ConvertValues (Binder binder, object[] args, ParameterInfo[] pinfo, CultureInfo culture, BindingFlags invokeAttr)
251                 {
252                         if (args == null) {
253                                 if (pinfo.Length == 0)
254                                         return;
255
256                                 throw new TargetParameterCountException ();
257                         }
258
259                         if (pinfo.Length != args.Length)
260                                 throw new TargetParameterCountException ();
261
262                         for (int i = 0; i < args.Length; ++i) {
263                                 var arg = args [i];
264                                 var pi = pinfo [i];
265                                 if (arg == Type.Missing) {
266                                         args [i] = pi.DefaultValue;
267                                         continue;
268                                 }
269
270                                 var rt = (RuntimeType) pi.ParameterType;
271                                 args [i] = rt.CheckValue (arg, binder, culture, invokeAttr);
272                         }
273                 }
274
275                 public override RuntimeMethodHandle MethodHandle { 
276                         get {
277                                 return new RuntimeMethodHandle (mhandle);
278                         } 
279                 }
280                 
281                 public override MethodAttributes Attributes { 
282                         get {
283                                 return MonoMethodInfo.GetAttributes (mhandle);
284                         } 
285                 }
286
287                 public override CallingConventions CallingConvention { 
288                         get {
289                                 return MonoMethodInfo.GetCallingConvention (mhandle);
290                         }
291                 }
292                 
293                 public override Type ReflectedType {
294                         get {
295                                 return reftype;
296                         }
297                 }
298                 public override Type DeclaringType {
299                         get {
300                                 return MonoMethodInfo.GetDeclaringType (mhandle);
301                         }
302                 }
303                 public override string Name {
304                         get {
305                                 if (name != null)
306                                         return name;
307                                 return get_name (this);
308                         }
309                 }
310                 
311                 public override bool IsDefined (Type attributeType, bool inherit) {
312                         return MonoCustomAttrs.IsDefined (this, attributeType, inherit);
313                 }
314
315                 public override object[] GetCustomAttributes( bool inherit) {
316                         return MonoCustomAttrs.GetCustomAttributes (this, inherit);
317                 }
318                 public override object[] GetCustomAttributes( Type attributeType, bool inherit) {
319                         return MonoCustomAttrs.GetCustomAttributes (this, attributeType, inherit);
320                 }
321
322                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
323                 internal static extern DllImportAttribute GetDllImportAttribute (IntPtr mhandle);
324
325                 internal object[] GetPseudoCustomAttributes ()
326                 {
327                         int count = 0;
328
329                         /* MS.NET doesn't report MethodImplAttribute */
330
331                         MonoMethodInfo info = MonoMethodInfo.GetMethodInfo (mhandle);
332                         if ((info.iattrs & MethodImplAttributes.PreserveSig) != 0)
333                                 count ++;
334                         if ((info.attrs & MethodAttributes.PinvokeImpl) != 0)
335                                 count ++;
336                         
337                         if (count == 0)
338                                 return null;
339                         object[] attrs = new object [count];
340                         count = 0;
341
342                         if ((info.iattrs & MethodImplAttributes.PreserveSig) != 0)
343                                 attrs [count ++] = new PreserveSigAttribute ();
344                         if ((info.attrs & MethodAttributes.PinvokeImpl) != 0) {
345                                 DllImportAttribute attr = GetDllImportAttribute (mhandle);
346                                 if ((info.iattrs & MethodImplAttributes.PreserveSig) != 0)
347                                         attr.PreserveSig = true;
348                                 attrs [count ++] = attr;
349                         }
350
351                         return attrs;
352                 }
353
354                 public override string ToString () {
355                         StringBuilder sb = new StringBuilder ();
356                         Type retType = ReturnType;
357                         if (Type.ShouldPrintFullName (retType))
358                                 sb.Append (retType.ToString ());
359                         else
360                                 sb.Append (retType.Name);
361                         sb.Append (" ");
362                         sb.Append (Name);
363                         if (IsGenericMethod) {
364                                 Type[] gen_params = GetGenericArguments ();
365                                 sb.Append ("[");
366                                 for (int j = 0; j < gen_params.Length; j++) {
367                                         if (j > 0)
368                                                 sb.Append (",");
369                                         sb.Append (gen_params [j].Name);
370                                 }
371                                 sb.Append ("]");
372                         }
373                         sb.Append ("(");
374
375                         var p = GetParametersInternal ();
376                         ParameterInfo.FormatParameters (sb, p);
377
378                         if ((CallingConvention & CallingConventions.VarArgs) != 0) {
379                                 if (p.Length > 0)
380                                         sb.Append (", ");
381                                 sb.Append ("...");
382                         }
383                         
384                         sb.Append (")");
385                         return sb.ToString ();
386                 }
387
388         
389                 // ISerializable
390                 public void GetObjectData(SerializationInfo info, StreamingContext context) 
391                 {
392                         Type[] genericArguments = IsGenericMethod && !IsGenericMethodDefinition
393                                 ? GetGenericArguments () : null;
394                         MemberInfoSerializationHolder.Serialize ( info, Name, ReflectedType, ToString(), MemberTypes.Method, genericArguments);
395                 }
396
397                 public override MethodInfo MakeGenericMethod (Type [] methodInstantiation)
398                 {
399                         if (methodInstantiation == null)
400                                 throw new ArgumentNullException ("methodInstantiation");
401
402                         if (!IsGenericMethodDefinition)
403                                 throw new InvalidOperationException ("not a generic method definition");
404
405                         /*FIXME add GetGenericArgumentsLength() internal vcall to speed this up*/
406                         if (GetGenericArguments ().Length != methodInstantiation.Length)
407                                 throw new ArgumentException ("Incorrect length");
408
409                         bool hasUserType = false;
410                         foreach (Type type in methodInstantiation) {
411                                 if (type == null)
412                                         throw new ArgumentNullException ();
413                                 if (!(type is MonoType))
414                                         hasUserType = true;
415                         }
416
417                         if (hasUserType)
418 #if FULL_AOT_RUNTIME
419                                 throw new NotSupportedException ("User types are not supported under full aot");
420 #else
421                                 return new MethodOnTypeBuilderInst (this, methodInstantiation);
422 #endif
423
424                         MethodInfo ret = MakeGenericMethod_impl (methodInstantiation);
425                         if (ret == null)
426                                 throw new ArgumentException (String.Format ("The method has {0} generic parameter(s) but {1} generic argument(s) were provided.", GetGenericArguments ().Length, methodInstantiation.Length));
427                         return ret;
428                 }
429
430                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
431                 extern MethodInfo MakeGenericMethod_impl (Type [] types);
432
433                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
434                 public override extern Type [] GetGenericArguments ();
435
436                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
437                 extern MethodInfo GetGenericMethodDefinition_impl ();
438
439                 public override MethodInfo GetGenericMethodDefinition ()
440                 {
441                         MethodInfo res = GetGenericMethodDefinition_impl ();
442                         if (res == null)
443                                 throw new InvalidOperationException ();
444
445                         return res;
446                 }
447
448                 public override extern bool IsGenericMethodDefinition {
449                         [MethodImplAttribute(MethodImplOptions.InternalCall)]
450                         get;
451                 }
452
453                 public override extern bool IsGenericMethod {
454                         [MethodImplAttribute(MethodImplOptions.InternalCall)]
455                         get;
456                 }
457
458                 public override bool ContainsGenericParameters {
459                         get {
460                                 if (IsGenericMethod) {
461                                         foreach (Type arg in GetGenericArguments ())
462                                                 if (arg.ContainsGenericParameters)
463                                                         return true;
464                                 }
465                                 return DeclaringType.ContainsGenericParameters;
466                         }
467                 }
468
469                 public override MethodBody GetMethodBody () {
470                         return GetMethodBody (mhandle);
471                 }
472
473                 public override IList<CustomAttributeData> GetCustomAttributesData () {
474                         return CustomAttributeData.GetCustomAttributes (this);
475                 }
476         }
477         
478
479         abstract class RuntimeConstructorInfo : ConstructorInfo
480         {
481         }
482
483         [Serializable()]
484         [StructLayout (LayoutKind.Sequential)]
485         internal class MonoCMethod : RuntimeConstructorInfo, ISerializable
486         {
487 #pragma warning disable 649             
488                 internal IntPtr mhandle;
489                 string name;
490                 Type reftype;
491 #pragma warning restore 649             
492                 
493                 public override MethodImplAttributes GetMethodImplementationFlags ()
494                 {
495                         return MonoMethodInfo.GetMethodImplementationFlags (mhandle);
496                 }
497
498                 public override ParameterInfo[] GetParameters ()
499                 {
500                         return MonoMethodInfo.GetParametersInfo (mhandle, this);
501                 }
502
503                 internal override ParameterInfo[] GetParametersInternal ()
504                 {
505                         return MonoMethodInfo.GetParametersInfo (mhandle, this);
506                 }               
507
508                 internal override int GetParametersCount ()
509                 {
510                         var pi = MonoMethodInfo.GetParametersInfo (mhandle, this);
511                         return pi == null ? 0 : pi.Length;
512                 }
513
514                 /*
515                  * InternalInvoke() receives the parameters correctly converted by the binder
516                  * to match the types of the method signature.
517                  */
518                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
519                 internal extern Object InternalInvoke (Object obj, Object[] parameters, out Exception exc);
520
521                 [DebuggerHidden]
522                 [DebuggerStepThrough]
523                 public override object Invoke (object obj, BindingFlags invokeAttr, Binder binder, object[] parameters, CultureInfo culture) 
524                 {
525                         if (obj == null) {
526                                 if (!IsStatic)
527                                         throw new TargetException ("Instance constructor requires a target");
528                         } else if (!DeclaringType.IsInstanceOfType (obj)) {
529                                 throw new TargetException ("Constructor does not match target type");                           
530                         }
531
532                         return DoInvoke (obj, invokeAttr, binder, parameters, culture);
533                 }
534
535                 object DoInvoke (object obj, BindingFlags invokeAttr, Binder binder, object[] parameters, CultureInfo culture) 
536                 {
537                         if (binder == null)
538                                 binder = Type.DefaultBinder;
539
540                         ParameterInfo[] pinfo = MonoMethodInfo.GetParametersInfo (mhandle, this);
541
542                         MonoMethod.ConvertValues (binder, parameters, pinfo, culture, invokeAttr);
543
544 #if !NET_2_1
545                         if (SecurityManager.SecurityEnabled) {
546                                 // sadly Attributes doesn't tell us which kind of security action this is so
547                                 // we must do it the hard way - and it also means that we can skip calling
548                                 // Attribute (which is another an icall)
549                                 SecurityManager.ReflectedLinkDemandInvoke (this);
550                         }
551 #endif
552
553                         if (obj == null && DeclaringType.ContainsGenericParameters)
554                                 throw new MemberAccessException ("Cannot create an instance of " + DeclaringType + " because Type.ContainsGenericParameters is true.");
555
556                         if ((invokeAttr & BindingFlags.CreateInstance) != 0 && DeclaringType.IsAbstract) {
557                                 throw new MemberAccessException (String.Format ("Cannot create an instance of {0} because it is an abstract class", DeclaringType));
558                         }
559
560                         return InternalInvoke (obj, parameters);
561                 }
562
563                 public object InternalInvoke (object obj, object[] parameters)
564                 {
565                         Exception exc;
566                         object o = null;
567
568                         try {
569                                 o = InternalInvoke (obj, parameters, out exc);
570 #if NET_2_1
571                         } catch (MethodAccessException) {
572                                 throw;
573 #endif
574                         } catch (Exception e) {
575                                 throw new TargetInvocationException (e);
576                         }
577
578                         if (exc != null)
579                                 throw exc;
580
581                         return obj == null ? o : null;
582                 }
583
584                 [DebuggerHidden]
585                 [DebuggerStepThrough]
586                 public override Object Invoke (BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
587                 {
588                         return DoInvoke (null, invokeAttr, binder, parameters, culture);
589                 }
590
591                 public override RuntimeMethodHandle MethodHandle { 
592                         get {
593                                 return new RuntimeMethodHandle (mhandle);
594                         } 
595                 }
596                 
597                 public override MethodAttributes Attributes { 
598                         get {
599                                 return MonoMethodInfo.GetAttributes (mhandle);
600                         } 
601                 }
602
603                 public override CallingConventions CallingConvention { 
604                         get {
605                                 return MonoMethodInfo.GetCallingConvention (mhandle);
606                         }
607                 }
608                 
609                 public override bool ContainsGenericParameters {
610                         get {
611                                 return DeclaringType.ContainsGenericParameters;
612                         }
613                 }
614
615                 public override Type ReflectedType {
616                         get {
617                                 return reftype;
618                         }
619                 }
620                 public override Type DeclaringType {
621                         get {
622                                 return MonoMethodInfo.GetDeclaringType (mhandle);
623                         }
624                 }
625                 public override string Name {
626                         get {
627                                 if (name != null)
628                                         return name;
629                                 return MonoMethod.get_name (this);
630                         }
631                 }
632
633                 public override bool IsDefined (Type attributeType, bool inherit) {
634                         return MonoCustomAttrs.IsDefined (this, attributeType, inherit);
635                 }
636
637                 public override object[] GetCustomAttributes( bool inherit) {
638                         return MonoCustomAttrs.GetCustomAttributes (this, inherit);
639                 }
640
641                 public override object[] GetCustomAttributes( Type attributeType, bool inherit) {
642                         return MonoCustomAttrs.GetCustomAttributes (this, attributeType, inherit);
643                 }
644
645                 public override MethodBody GetMethodBody () {
646                         return GetMethodBody (mhandle);
647                 }
648
649                 public override string ToString () {
650                         StringBuilder sb = new StringBuilder ();
651                         sb.Append ("Void ");
652                         sb.Append (Name);
653                         sb.Append ("(");
654                         ParameterInfo[] p = GetParameters ();
655                         for (int i = 0; i < p.Length; ++i) {
656                                 if (i > 0)
657                                         sb.Append (", ");
658                                 sb.Append (p[i].ParameterType.Name);
659                         }
660                         if (CallingConvention == CallingConventions.Any)
661                                 sb.Append (", ...");
662                         sb.Append (")");
663                         return sb.ToString ();
664                 }
665
666                 // ISerializable
667                 public void GetObjectData(SerializationInfo info, StreamingContext context) 
668                 {
669                         MemberInfoSerializationHolder.Serialize ( info, Name, ReflectedType, ToString(), MemberTypes.Constructor);
670                 }
671
672                 public override IList<CustomAttributeData> GetCustomAttributesData () {
673                         return CustomAttributeData.GetCustomAttributes (this);
674                 }
675         }
676 }