Add locking to EventWaitHandle.Set/Reset to avoid crashes when another thread dispose...
[mono.git] / mcs / class / corlib / System.Reflection.Emit / MethodOnTypeBuilderInst.cs
index 65246ea665e648274394ba6602f0ecd28231cf4f..6b976e8a9812f687ae174d48d45d902f9ecc4ed1 100644 (file)
@@ -41,12 +41,13 @@ namespace System.Reflection.Emit
        {
                #region Keep in sync with object-internals.h
                Type instantiation;
-               internal MethodBuilder base_method; /*This is the base method definition, it must be non-inflated and belong to a non-inflated type.*/
+               MethodInfo base_method; /*This is the base method definition, it must be non-inflated and belong to a non-inflated type.*/
                Type[] method_arguments;
-               MethodOnTypeBuilderInst generic_method_definition;
                #endregion
+               MethodInfo generic_method_definition;
+               int is_compiler_context = -1;
 
-               public MethodOnTypeBuilderInst (MonoGenericClass instantiation, MethodBuilder base_method)
+               public MethodOnTypeBuilderInst (MonoGenericClass instantiation, MethodInfo base_method)
                {
                        this.instantiation = instantiation;
                        this.base_method = base_method;
@@ -61,6 +62,33 @@ namespace System.Reflection.Emit
                        this.generic_method_definition = gmd;
                }
 
+               internal MethodOnTypeBuilderInst (MethodInfo method, Type[] typeArguments)
+               {
+                       this.instantiation = method.DeclaringType;
+                       this.base_method = ExtractBaseMethod (method);
+                       this.method_arguments = new Type [typeArguments.Length];
+                       typeArguments.CopyTo (this.method_arguments, 0);
+                       if (base_method != method)
+                               this.generic_method_definition = method;
+               }
+
+               static MethodInfo ExtractBaseMethod (MethodInfo info)
+               {
+                       if (info is MethodBuilder)
+                               return info;
+                       if (info is MethodOnTypeBuilderInst)
+                               return ((MethodOnTypeBuilderInst)info).base_method;
+
+                       if (info.IsGenericMethod)
+                               info = info.GetGenericMethodDefinition ();
+
+                       Type t = info.DeclaringType;
+                       if (!t.IsGenericType || t.IsGenericTypeDefinition)
+                               return info;
+
+                       return (MethodInfo)t.Module.ResolveMethod (info.MetadataToken);
+               }
+
                internal Type[] GetTypeArgs ()
                {
                        if (!instantiation.IsGenericType || instantiation.IsGenericParameter)
@@ -70,7 +98,18 @@ namespace System.Reflection.Emit
                }
 
                internal bool IsCompilerContext {
-                       get { return ((ModuleBuilder)base_method.Module).assemblyb.IsCompilerContext; }
+                       get {
+                               if (is_compiler_context == -1) {
+                                       bool is_cc = false;
+                                       is_cc |= instantiation.IsCompilerContext;
+                                       if (!is_cc && method_arguments != null) {
+                                               foreach (Type t in method_arguments)
+                                                       is_cc |= t.IsCompilerContext;
+                                       }
+                                       is_compiler_context = is_cc ? 1 : 0;
+                               }
+                               return is_compiler_context == 1;
+                       }
                }
 
                //
@@ -105,17 +144,23 @@ namespace System.Reflection.Emit
 
                public override bool IsDefined (Type attributeType, bool inherit)
                {
-                       throw new NotSupportedException ();
+                       if (!IsCompilerContext)
+                               throw new NotSupportedException ();
+                       return base_method.IsDefined (attributeType, inherit);
                }
 
                public override object [] GetCustomAttributes (bool inherit)
                {
-                       throw new NotSupportedException ();
+                       if (!IsCompilerContext)
+                               throw new NotSupportedException ();
+                       return base_method.GetCustomAttributes (inherit);
                }
 
                public override object [] GetCustomAttributes (Type attributeType, bool inherit)
                {
-                       throw new NotSupportedException ();
+                       if (!IsCompilerContext)
+                               throw new NotSupportedException ();
+                       return base_method.GetCustomAttributes (attributeType, inherit);
                }
 
                public override string ToString ()
@@ -147,13 +192,24 @@ namespace System.Reflection.Emit
 
                public override ParameterInfo [] GetParameters ()
                {
+                       ParameterInfo [] res = null;
                        if (!IsCompilerContext)
                                throw new NotSupportedException ();
 
-                       ParameterInfo [] res = new ParameterInfo [base_method.parameters.Length];
-                       for (int i = 0; i < base_method.parameters.Length; i++) {
-                               Type type = MonoGenericClass.InflateType (base_method.parameters [i], GetTypeArgs (), method_arguments);
-                               res [i] = new ParameterInfo (base_method.pinfo == null ? null : base_method.pinfo [i + 1], type, this, i + 1);
+                       if (base_method is MethodBuilder) {
+                               MethodBuilder mb = (MethodBuilder)base_method;
+                               res = new ParameterInfo [mb.parameters.Length];
+                               for (int i = 0; i < mb.parameters.Length; i++) {
+                                       Type type = MonoGenericClass.InflateType (mb.parameters [i], GetTypeArgs (), method_arguments);
+                                       res [i] = new ParameterInfo (mb.pinfo == null ? null : mb.pinfo [i + 1], type, this, i + 1);
+                               }
+                       } else {
+                               ParameterInfo[] base_params = base_method.GetParameters ();
+                               res = new ParameterInfo [base_params.Length];
+                               for (int i = 0; i < base_params.Length; i++) {
+                                       Type type = MonoGenericClass.InflateType (base_params [i].ParameterType, GetTypeArgs (), method_arguments);
+                                       res [i] = new ParameterInfo (base_params [i], type, this, i + 1);
+                               }
                        }
                        return res;
                }
@@ -194,30 +250,30 @@ namespace System.Reflection.Emit
                        }
                }
 
-               public override MethodInfo MakeGenericMethod (params Type [] typeArguments)
+               public override MethodInfo MakeGenericMethod (params Type [] methodInstantiation)
                {
-                       if (base_method.generic_params == null || method_arguments != null)
-                               throw new NotSupportedException (); //FIXME is this the right exception?
+                       if (!base_method.IsGenericMethodDefinition || (method_arguments != null && !IsCompilerContext))
+                               throw new InvalidOperationException ("Method is not a generic method definition");
 
-                       if (typeArguments == null)
-                               throw new ArgumentNullException ("typeArguments");
+                       if (methodInstantiation == null)
+                               throw new ArgumentNullException ("methodInstantiation");
 
-                       foreach (Type t in typeArguments) {
-                               if (t == null)
-                                       throw new ArgumentNullException ("typeArguments");
-                       }
+                       if (base_method.GetGenericArguments ().Length != methodInstantiation.Length)
+                               throw new ArgumentException ("Incorrect length", "methodInstantiation");
 
-                       if (base_method.generic_params.Length != typeArguments.Length)
-                               throw new ArgumentException ("Invalid argument array length");
+                       foreach (Type type in methodInstantiation) {
+                               if (type == null)
+                                       throw new ArgumentNullException ("methodInstantiation");
+                       }
 
-                       return new MethodOnTypeBuilderInst (this, typeArguments);
+                       return new MethodOnTypeBuilderInst (this, methodInstantiation);
                }
 
                public override Type [] GetGenericArguments ()
                {
-                       if (base_method.generic_params == null)
+                       if (!base_method.IsGenericMethodDefinition)
                                return null;
-                       Type[] source = method_arguments ?? base_method.generic_params;
+                       Type[] source = method_arguments ?? base_method.GetGenericArguments ();
                        Type[] result = new Type [source.Length];
                        source.CopyTo (result, 0);
                        return result;
@@ -225,12 +281,14 @@ namespace System.Reflection.Emit
 
                public override MethodInfo GetGenericMethodDefinition ()
                {
-                       return (MethodInfo)generic_method_definition ?? base_method;
+                       return generic_method_definition ?? base_method;
                }
 
                public override bool ContainsGenericParameters {
                        get {
-                               if (base_method.generic_params == null)
+                               if (base_method.ContainsGenericParameters)
+                                       return true;
+                               if (!base_method.IsGenericMethodDefinition)
                                        throw new NotSupportedException ();
                                if (method_arguments == null)
                                        return true;
@@ -244,13 +302,13 @@ namespace System.Reflection.Emit
 
                public override bool IsGenericMethodDefinition {
                        get {
-                               return base_method.generic_params != null && method_arguments == null;
+                               return base_method.IsGenericMethodDefinition && method_arguments == null;
                        }
                }
 
                public override bool IsGenericMethod {
                        get {
-                               return base_method.generic_params != null;
+                               return base_method.IsGenericMethodDefinition;
                        }
                }