Merge pull request #487 from mayerwin/patch-1
[mono.git] / mcs / class / corlib / System.Reflection.Emit / MethodOnTypeBuilderInst.cs
index a1b2dd6739bdc203bfe70792d15d39781b5a46f1..aa19ecef3bf94e12a6756ec021d142fb4f3e4514 100644 (file)
 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 //
 
+#if !FULL_AOT_RUNTIME
 using System;
 using System.Globalization;
 using System.Reflection;
+using System.Text;
+using System.Runtime.InteropServices;
 
-#if NET_2_0
 
 namespace System.Reflection.Emit
 {
        /*
         * This class represents a method of an instantiation of a generic type builder.
         */
+       [StructLayout (LayoutKind.Sequential)]
        internal class MethodOnTypeBuilderInst : MethodInfo
        {
                #region Keep in sync with object-internals.h
-               MonoGenericClass instantiation;
-               internal MethodBuilder mb;
+               Type instantiation;
+               MethodInfo base_method; /*This is the base method definition, it must be non-inflated and belong to a non-inflated type.*/
+               Type[] method_arguments;
                #endregion
+               MethodInfo generic_method_definition;
 
-               public MethodOnTypeBuilderInst (MonoGenericClass instantiation, MethodBuilder mb)
+               public MethodOnTypeBuilderInst (MonoGenericClass instantiation, MethodInfo base_method)
                {
                        this.instantiation = instantiation;
-                       this.mb = mb;
+                       this.base_method = base_method;
+               }
+
+               internal MethodOnTypeBuilderInst (MethodOnTypeBuilderInst gmd, Type[] typeArguments)
+               {
+                       this.instantiation = gmd.instantiation;
+                       this.base_method = gmd.base_method;
+                       this.method_arguments = new Type [typeArguments.Length];
+                       typeArguments.CopyTo (this.method_arguments, 0);
+                       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)
+                               return null;                            
+
+                       return instantiation.GetGenericArguments ();
                }
 
                //
@@ -63,7 +112,7 @@ namespace System.Reflection.Emit
 
                public override string Name {
                        get {
-                               return mb.Name;
+                               return base_method.Name;
                        }
                }
 
@@ -75,9 +124,7 @@ namespace System.Reflection.Emit
 
                public override Type ReturnType {
                        get { 
-                               if (!((ModuleBuilder)mb.Module).assemblyb.IsCompilerContext)
-                                       return mb.ReturnType;
-                               return instantiation.InflateType (mb.ReturnType);
+                               return base_method.ReturnType;
                        }
                }
 
@@ -96,39 +143,39 @@ namespace System.Reflection.Emit
                        throw new NotSupportedException ();
                }
 
+               public override string ToString ()
+               {
+                        //IEnumerable`1 get_Item(TKey)
+                        StringBuilder sb = new StringBuilder (ReturnType.ToString ());
+                        sb.Append (" ");
+                        sb.Append (base_method.Name);
+                        sb.Append ("(");
+                        sb.Append (")");
+                        return sb.ToString ();
+               }
                //
                // MethodBase members
                //
 
                public override MethodImplAttributes GetMethodImplementationFlags ()
                {
-                       return mb.GetMethodImplementationFlags ();
+                       return base_method.GetMethodImplementationFlags ();
                }
 
                public override ParameterInfo [] GetParameters ()
                {
-                       if (!((ModuleBuilder)mb.Module).assemblyb.IsCompilerContext)
-                               throw new NotSupportedException ();
-
-                       ParameterInfo [] res = new ParameterInfo [mb.parameters.Length];
-                       for (int i = 0; i < mb.parameters.Length; i++) {
-                               Type type = instantiation.InflateType (mb.parameters [i]);
-                               res [i] = new ParameterInfo (mb.pinfo == null ? null : mb.pinfo [i + 1], type, this, i + 1);
-                       }
-                       return res;
+                       throw new NotSupportedException ();
                }
 
                public override int MetadataToken {
                        get {
-                               if (!((ModuleBuilder)mb.Module).assemblyb.IsCompilerContext)
-                                       return base.MetadataToken;
-                               return mb.MetadataToken;
+                               return base.MetadataToken;
                        }
                }
 
                internal override int GetParameterCount ()
                {
-                       return mb.GetParameterCount ();
+                       return base_method.GetParameterCount ();
                }
 
                public override Object Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
@@ -144,44 +191,75 @@ namespace System.Reflection.Emit
 
                public override MethodAttributes Attributes {
                        get {
-                               return mb.Attributes;
+                               return base_method.Attributes;
                        }
                }
 
                public override CallingConventions CallingConvention {
                        get {
-                               return mb.CallingConvention;
+                               return base_method.CallingConvention;
                        }
                }
 
+               public override MethodInfo MakeGenericMethod (params Type [] methodInstantiation)
+               {
+                       if (!base_method.IsGenericMethodDefinition || (method_arguments != null))
+                               throw new InvalidOperationException ("Method is not a generic method definition");
+
+                       if (methodInstantiation == null)
+                               throw new ArgumentNullException ("methodInstantiation");
+
+                       if (base_method.GetGenericArguments ().Length != methodInstantiation.Length)
+                               throw new ArgumentException ("Incorrect length", "methodInstantiation");
+
+                       foreach (Type type in methodInstantiation) {
+                               if (type == null)
+                                       throw new ArgumentNullException ("methodInstantiation");
+                       }
+
+                       return new MethodOnTypeBuilderInst (this, methodInstantiation);
+               }
+
                public override Type [] GetGenericArguments ()
                {
-                       //FIXME test that once we support generic methods 
-                       return mb.GetGenericArguments ();
+                       if (!base_method.IsGenericMethodDefinition)
+                               return null;
+                       Type[] source = method_arguments ?? base_method.GetGenericArguments ();
+                       Type[] result = new Type [source.Length];
+                       source.CopyTo (result, 0);
+                       return result;
                }
 
                public override MethodInfo GetGenericMethodDefinition ()
                {
-                       return mb;
+                       return generic_method_definition ?? base_method;
                }
 
                public override bool ContainsGenericParameters {
                        get {
-                               throw new NotSupportedException ();
+                               if (base_method.ContainsGenericParameters)
+                                       return true;
+                               if (!base_method.IsGenericMethodDefinition)
+                                       throw new NotSupportedException ();
+                               if (method_arguments == null)
+                                       return true;
+                               foreach (Type t in method_arguments) {
+                                       if (t.ContainsGenericParameters)
+                                               return true;
+                               }
+                               return false;
                        }
                }
 
                public override bool IsGenericMethodDefinition {
                        get {
-                               //FIXME test that once we support generic methods 
-                               return mb.IsGenericMethodDefinition;
+                               return base_method.IsGenericMethodDefinition && method_arguments == null;
                        }
                }
 
                public override bool IsGenericMethod {
                        get {
-                               //FIXME test that once we support generic methods 
-                               return mb.IsGenericMethod;
+                               return base_method.IsGenericMethodDefinition;
                        }
                }