New test.
[mono.git] / mcs / class / corlib / System.Reflection.Emit / MethodOnTypeBuilderInst.cs
1 //
2 // System.Reflection.Emit/MethodOnTypeBuilderInst.cs
3 //
4 // Author:
5 //   Zoltan Varga (vargaz@gmail.com)
6 //
7 //
8 // Copyright (C) 2008 Novell, Inc (http://www.novell.com)
9 //
10 // Permission is hereby granted, free of charge, to any person obtaining
11 // a copy of this software and associated documentation files (the
12 // "Software"), to deal in the Software without restriction, including
13 // without limitation the rights to use, copy, modify, merge, publish,
14 // distribute, sublicense, and/or sell copies of the Software, and to
15 // permit persons to whom the Software is furnished to do so, subject to
16 // the following conditions:
17 // 
18 // The above copyright notice and this permission notice shall be
19 // included in all copies or substantial portions of the Software.
20 // 
21 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
25 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 //
29
30 using System;
31 using System.Globalization;
32 using System.Reflection;
33 using System.Text;
34
35 namespace System.Reflection.Emit
36 {
37         /*
38          * This class represents a method of an instantiation of a generic type builder.
39          */
40         internal class MethodOnTypeBuilderInst : MethodInfo
41         {
42                 #region Keep in sync with object-internals.h
43                 Type instantiation;
44                 MethodInfo base_method; /*This is the base method definition, it must be non-inflated and belong to a non-inflated type.*/
45                 Type[] method_arguments;
46                 #endregion
47                 MethodInfo generic_method_definition;
48                 int is_compiler_context = -1;
49
50                 public MethodOnTypeBuilderInst (MonoGenericClass instantiation, MethodInfo base_method)
51                 {
52                         this.instantiation = instantiation;
53                         this.base_method = base_method;
54                 }
55
56                 internal MethodOnTypeBuilderInst (MethodOnTypeBuilderInst gmd, Type[] typeArguments)
57                 {
58                         this.instantiation = gmd.instantiation;
59                         this.base_method = gmd.base_method;
60                         this.method_arguments = new Type [typeArguments.Length];
61                         typeArguments.CopyTo (this.method_arguments, 0);
62                         this.generic_method_definition = gmd;
63                 }
64
65                 internal MethodOnTypeBuilderInst (MethodInfo method, Type[] typeArguments)
66                 {
67                         this.instantiation = method.DeclaringType;
68                         this.base_method = ExtractBaseMethod (method);
69                         this.method_arguments = new Type [typeArguments.Length];
70                         typeArguments.CopyTo (this.method_arguments, 0);
71                         if (base_method != method)
72                                 this.generic_method_definition = method;
73                 }
74
75                 static MethodInfo ExtractBaseMethod (MethodInfo info)
76                 {
77                         if (info is MethodBuilder)
78                                 return info;
79                         if (info is MethodOnTypeBuilderInst)
80                                 return ((MethodOnTypeBuilderInst)info).base_method;
81
82                         if (info.IsGenericMethod)
83                                 info = info.GetGenericMethodDefinition ();
84
85                         Type t = info.DeclaringType;
86                         if (!t.IsGenericType || t.IsGenericTypeDefinition)
87                                 return info;
88
89                         return (MethodInfo)t.Module.ResolveMethod (info.MetadataToken);
90                 }
91
92                 internal Type[] GetTypeArgs ()
93                 {
94                         if (!instantiation.IsGenericType || instantiation.IsGenericParameter)
95                                 return null;                            
96
97                         return instantiation.GetGenericArguments ();
98                 }
99
100                 internal bool IsCompilerContext {
101                         get {
102                                 if (is_compiler_context == -1) {
103                                         bool is_cc = false;
104                                         is_cc |= instantiation.IsCompilerContext;
105                                         if (!is_cc && method_arguments != null) {
106                                                 foreach (Type t in method_arguments)
107                                                         is_cc |= t.IsCompilerContext;
108                                         }
109                                         is_compiler_context = is_cc ? 1 : 0;
110                                 }
111                                 return is_compiler_context == 1;
112                         }
113                 }
114
115                 //
116                 // MemberInfo members
117                 //
118                 
119                 public override Type DeclaringType {
120                         get {
121                                 return instantiation;
122                         }
123                 }
124
125                 public override string Name {
126                         get {
127                                 return base_method.Name;
128                         }
129                 }
130
131                 public override Type ReflectedType {
132                         get {
133                                 return instantiation;
134                         }
135                 }
136
137                 public override Type ReturnType {
138                         get { 
139                                 if (!IsCompilerContext)
140                                         return base_method.ReturnType;
141                                 return MonoGenericClass.InflateType (base_method.ReturnType, GetTypeArgs (), method_arguments);
142                         }
143                 }
144
145                 public override bool IsDefined (Type attributeType, bool inherit)
146                 {
147                         if (!IsCompilerContext)
148                                 throw new NotSupportedException ();
149                         return base_method.IsDefined (attributeType, inherit);
150                 }
151
152                 public override object [] GetCustomAttributes (bool inherit)
153                 {
154                         if (!IsCompilerContext)
155                                 throw new NotSupportedException ();
156                         return base_method.GetCustomAttributes (inherit);
157                 }
158
159                 public override object [] GetCustomAttributes (Type attributeType, bool inherit)
160                 {
161                         if (!IsCompilerContext)
162                                 throw new NotSupportedException ();
163                         return base_method.GetCustomAttributes (attributeType, inherit);
164                 }
165
166                 public override string ToString ()
167                 {
168                          //IEnumerable`1 get_Item(TKey)
169                          StringBuilder sb = new StringBuilder (ReturnType.ToString ());
170                          sb.Append (" ");
171                          sb.Append (base_method.Name);
172                          sb.Append ("(");
173                          if (IsCompilerContext) {
174                                  ParameterInfo [] par = GetParameters ();
175                                  for (int i = 0; i < par.Length; ++i) {
176                                         if (i > 0)
177                                                 sb.Append (", ");
178                                         sb.Append (par [i].ParameterType);
179                                  }
180                         }
181                          sb.Append (")");
182                          return sb.ToString ();
183                 }
184                 //
185                 // MethodBase members
186                 //
187
188                 public override MethodImplAttributes GetMethodImplementationFlags ()
189                 {
190                         return base_method.GetMethodImplementationFlags ();
191                 }
192
193                 public override ParameterInfo [] GetParameters ()
194                 {
195                         ParameterInfo [] res = null;
196                         if (!IsCompilerContext)
197                                 throw new NotSupportedException ();
198
199                         if (base_method is MethodBuilder) {
200                                 MethodBuilder mb = (MethodBuilder)base_method;
201                                 res = new ParameterInfo [mb.parameters.Length];
202                                 for (int i = 0; i < mb.parameters.Length; i++) {
203                                         Type type = MonoGenericClass.InflateType (mb.parameters [i], GetTypeArgs (), method_arguments);
204                                         res [i] = new ParameterInfo (mb.pinfo == null ? null : mb.pinfo [i + 1], type, this, i + 1);
205                                 }
206                         } else {
207                                 ParameterInfo[] base_params = base_method.GetParameters ();
208                                 res = new ParameterInfo [base_params.Length];
209                                 for (int i = 0; i < base_params.Length; i++) {
210                                         Type type = MonoGenericClass.InflateType (base_params [i].ParameterType, GetTypeArgs (), method_arguments);
211                                         res [i] = new ParameterInfo (base_params [i], type, this, i + 1);
212                                 }
213                         }
214                         return res;
215                 }
216
217                 public override int MetadataToken {
218                         get {
219                                 if (!IsCompilerContext)
220                                         return base.MetadataToken;
221                                 return base_method.MetadataToken;
222                         }
223                 }
224
225                 internal override int GetParameterCount ()
226                 {
227                         return base_method.GetParameterCount ();
228                 }
229
230                 public override Object Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
231                 {
232                         throw new NotSupportedException ();
233                 }
234
235                 public override RuntimeMethodHandle MethodHandle {
236                         get {
237                                 throw new NotSupportedException ();
238                         }
239                 }
240
241                 public override MethodAttributes Attributes {
242                         get {
243                                 return base_method.Attributes;
244                         }
245                 }
246
247                 public override CallingConventions CallingConvention {
248                         get {
249                                 return base_method.CallingConvention;
250                         }
251                 }
252
253                 public override MethodInfo MakeGenericMethod (params Type [] methodInstantiation)
254                 {
255                         if (!base_method.IsGenericMethodDefinition || (method_arguments != null && !IsCompilerContext))
256                                 throw new InvalidOperationException ("Method is not a generic method definition");
257
258                         if (methodInstantiation == null)
259                                 throw new ArgumentNullException ("methodInstantiation");
260
261                         if (base_method.GetGenericArguments ().Length != methodInstantiation.Length)
262                                 throw new ArgumentException ("Incorrect length", "methodInstantiation");
263
264                         foreach (Type type in methodInstantiation) {
265                                 if (type == null)
266                                         throw new ArgumentNullException ("methodInstantiation");
267                         }
268
269                         return new MethodOnTypeBuilderInst (this, methodInstantiation);
270                 }
271
272                 public override Type [] GetGenericArguments ()
273                 {
274                         if (!base_method.IsGenericMethodDefinition)
275                                 return null;
276                         Type[] source = method_arguments ?? base_method.GetGenericArguments ();
277                         Type[] result = new Type [source.Length];
278                         source.CopyTo (result, 0);
279                         return result;
280                 }
281
282                 public override MethodInfo GetGenericMethodDefinition ()
283                 {
284                         return generic_method_definition ?? base_method;
285                 }
286
287                 public override bool ContainsGenericParameters {
288                         get {
289                                 if (base_method.ContainsGenericParameters)
290                                         return true;
291                                 if (!base_method.IsGenericMethodDefinition)
292                                         throw new NotSupportedException ();
293                                 if (method_arguments == null)
294                                         return true;
295                                 foreach (Type t in method_arguments) {
296                                         if (t.ContainsGenericParameters)
297                                                 return true;
298                                 }
299                                 return false;
300                         }
301                 }
302
303                 public override bool IsGenericMethodDefinition {
304                         get {
305                                 return base_method.IsGenericMethodDefinition && method_arguments == null;
306                         }
307                 }
308
309                 public override bool IsGenericMethod {
310                         get {
311                                 return base_method.IsGenericMethodDefinition;
312                         }
313                 }
314
315                 //
316                 // MethodInfo members
317                 //
318
319                 public override MethodInfo GetBaseDefinition ()
320                 {
321                         throw new NotSupportedException ();
322                 }
323
324                 public override ICustomAttributeProvider ReturnTypeCustomAttributes {
325                         get {
326                                 throw new NotSupportedException ();
327                         }
328                 }
329         }
330 }
331