Merge pull request #1909 from esdrubal/reflection
[mono.git] / mcs / class / corlib / System.Reflection.Emit / ConstructorBuilder.cs
1 //
2 // System.Reflection.Emit.ConstructorBuilder.cs
3 //
4 // Author:
5 //   Paolo Molaro (lupus@ximian.com)
6 //
7 // (C) 2001 Ximian, Inc.  http://www.ximian.com
8 //
9
10 //
11 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
12 //
13 // Permission is hereby granted, free of charge, to any person obtaining
14 // a copy of this software and associated documentation files (the
15 // "Software"), to deal in the Software without restriction, including
16 // without limitation the rights to use, copy, modify, merge, publish,
17 // distribute, sublicense, and/or sell copies of the Software, and to
18 // permit persons to whom the Software is furnished to do so, subject to
19 // the following conditions:
20 // 
21 // The above copyright notice and this permission notice shall be
22 // included in all copies or substantial portions of the Software.
23 // 
24 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
28 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
29 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
30 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31 //
32
33 #if !FULL_AOT_RUNTIME
34 using System;
35 using System.Collections.Generic;
36 using System.Reflection;
37 using System.Reflection.Emit;
38 using System.Globalization;
39 using System.Security;
40 using System.Security.Permissions;
41 using System.Runtime.InteropServices;
42 using System.Diagnostics.SymbolStore;
43
44 namespace System.Reflection.Emit {
45
46         [ComVisible (true)]
47         [ComDefaultInterface (typeof (_ConstructorBuilder))]
48         [ClassInterface (ClassInterfaceType.None)]
49         [StructLayout (LayoutKind.Sequential)]
50         public sealed class ConstructorBuilder : ConstructorInfo, _ConstructorBuilder {
51         
52 #pragma warning disable 169, 414
53                 private RuntimeMethodHandle mhandle;
54                 private ILGenerator ilgen;
55                 internal Type[] parameters;
56                 private MethodAttributes attrs;
57                 private MethodImplAttributes iattrs;
58                 private int table_idx;
59                 private CallingConventions call_conv;
60                 private TypeBuilder type;
61                 internal ParameterBuilder[] pinfo;
62                 private CustomAttributeBuilder[] cattrs;
63                 private bool init_locals = true;
64                 private Type[][] paramModReq;
65                 private Type[][] paramModOpt;
66                 private RefEmitPermissionSet[] permissions;
67 #pragma warning restore 169, 414
68
69                 internal ConstructorBuilder (TypeBuilder tb, MethodAttributes attributes, CallingConventions callingConvention, Type[] parameterTypes, Type[][] paramModReq, Type[][] paramModOpt)
70                 {
71                         attrs = attributes | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName;
72                         call_conv = callingConvention;
73                         if (parameterTypes != null) {
74                                 for (int i = 0; i < parameterTypes.Length; ++i)
75                                         if (parameterTypes [i] == null)
76                                                 throw new ArgumentException ("Elements of the parameterTypes array cannot be null", "parameterTypes");
77
78                                 this.parameters = new Type [parameterTypes.Length];
79                                 System.Array.Copy (parameterTypes, this.parameters, parameterTypes.Length);
80                         }
81                         type = tb;
82                         this.paramModReq = paramModReq;
83                         this.paramModOpt = paramModOpt;
84                         table_idx = get_next_table_index (this, 0x06, true);
85
86                         ((ModuleBuilder) tb.Module).RegisterToken (this, GetToken ().Token);
87                 }
88
89                 [MonoTODO]
90                 public override CallingConventions CallingConvention {
91                         get {
92                                 return call_conv;
93                         }
94                 }
95
96                 public bool InitLocals {
97                         get {
98                                 return init_locals;
99                         }
100                         set {
101                                 init_locals = value;
102                         }
103                 }
104
105                 internal TypeBuilder TypeBuilder {
106                         get {
107                                 return type;
108                         }
109                 }
110                 
111                 public override MethodImplAttributes GetMethodImplementationFlags ()
112                 {
113                         return iattrs;
114                 }
115
116                 public override ParameterInfo[] GetParameters ()
117                 {
118                         if (!type.is_created)
119                                 throw not_created ();
120
121                         return GetParametersInternal ();
122                 }
123
124                 internal override ParameterInfo [] GetParametersInternal ()
125                 {
126                         if (parameters == null)
127                                 return EmptyArray<ParameterInfo>.Value;
128
129                         ParameterInfo [] retval = new ParameterInfo [parameters.Length];
130                         for (int i = 0; i < parameters.Length; i++)
131                                 retval [i] = ParameterInfo.New (pinfo == null ? null
132                                         : pinfo [i + 1], parameters [i], this, i + 1);
133
134                         return retval;
135                 }
136                 
137                 internal override int GetParametersCount ()
138                 {
139                         if (parameters == null)
140                                 return 0;
141                         
142                         return parameters.Length;
143                 }
144
145                 internal override Type GetParameterType (int pos) {
146                         return parameters [pos];
147                 }
148                 
149                 public override Object Invoke (Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
150                 {
151                         throw not_supported ();
152                 }
153
154                 public override object Invoke (BindingFlags invokeAttr, Binder binder, object[] parameters, CultureInfo culture)
155                 {
156                         throw not_supported ();
157                 }
158
159                 public override RuntimeMethodHandle MethodHandle {
160                         get {
161                                 throw not_supported ();
162                         }
163                 }
164
165                 public override MethodAttributes Attributes {
166                         get {
167                                 return attrs;
168                         }
169                 }
170
171                 public override Type ReflectedType {
172                         get {
173                                 return type;
174                         }
175                 }
176
177                 public override Type DeclaringType {
178                         get {
179                                 return type;
180                         }
181                 }
182
183                 [Obsolete]
184                 public Type ReturnType {
185                         get {
186                                 return null;
187                         }
188                 }
189
190                 public override string Name {
191                         get {
192                                 return (attrs & MethodAttributes.Static) != 0 ? ConstructorInfo.TypeConstructorName : ConstructorInfo.ConstructorName;
193                         }
194                 }
195
196                 public string Signature {
197                         get {
198                                 return "constructor signature";
199                         }
200                 }
201
202                 public void AddDeclarativeSecurity (SecurityAction action, PermissionSet pset)
203                 {
204 #if !NET_2_1
205                         if (pset == null)
206                                 throw new ArgumentNullException ("pset");
207                         if ((action == SecurityAction.RequestMinimum) ||
208                                 (action == SecurityAction.RequestOptional) ||
209                                 (action == SecurityAction.RequestRefuse))
210                                 throw new ArgumentOutOfRangeException ("action", "Request* values are not permitted");
211
212                         RejectIfCreated ();
213
214                         if (permissions != null) {
215                                 /* Check duplicate actions */
216                                 foreach (RefEmitPermissionSet set in permissions)
217                                         if (set.action == action)
218                                                 throw new InvalidOperationException ("Multiple permission sets specified with the same SecurityAction.");
219
220                                 RefEmitPermissionSet[] new_array = new RefEmitPermissionSet [permissions.Length + 1];
221                                 permissions.CopyTo (new_array, 0);
222                                 permissions = new_array;
223                         }
224                         else
225                                 permissions = new RefEmitPermissionSet [1];
226
227                         permissions [permissions.Length - 1] = new RefEmitPermissionSet (action, pset.ToXml ().ToString ());
228                         attrs |= MethodAttributes.HasSecurity;
229 #endif
230                 }
231
232                 public ParameterBuilder DefineParameter (int iSequence, ParameterAttributes attributes, string strParamName)
233                 {
234                         if (iSequence < 1 || iSequence > GetParametersCount ())
235                                 throw new ArgumentOutOfRangeException ("iSequence");
236                         if (type.is_created)
237                                 throw not_after_created ();
238
239                         ParameterBuilder pb = new ParameterBuilder (this, iSequence, attributes, strParamName);
240                         if (pinfo == null)
241                                 pinfo = new ParameterBuilder [parameters.Length + 1];
242                         pinfo [iSequence] = pb;
243                         return pb;
244                 }
245
246                 public override bool IsDefined (Type attributeType, bool inherit)
247                 {
248                         throw not_supported ();
249                 }
250
251                 public override object [] GetCustomAttributes (bool inherit)
252                 {
253                         throw not_supported ();
254                 }
255
256                 public override object [] GetCustomAttributes (Type attributeType, bool inherit)
257                 {
258                         throw not_supported ();
259                 }
260
261                 public ILGenerator GetILGenerator ()
262                 {
263                         return GetILGenerator (64);
264                 }
265
266                 public ILGenerator GetILGenerator (int streamSize)
267                 {
268                         if (ilgen != null)
269                                 return ilgen;
270                         ilgen = new ILGenerator (type.Module, ((ModuleBuilder)type.Module).GetTokenGenerator (), streamSize);
271                         return ilgen;
272                 }
273
274                 public void SetMethodBody (byte[] il, int maxStack, byte[] localSignature,
275                         IEnumerable<ExceptionHandler> exceptionHandlers, IEnumerable<int> tokenFixups)
276                 {
277                         var ilgen = GetILGenerator ();
278                         ilgen.Init (il, maxStack, localSignature, exceptionHandlers, tokenFixups);
279                 }
280
281
282                 public void SetCustomAttribute (CustomAttributeBuilder customBuilder)
283                 {
284                         if (customBuilder == null)
285                                 throw new ArgumentNullException ("customBuilder");
286
287                         string attrname = customBuilder.Ctor.ReflectedType.FullName;
288                         if (attrname == "System.Runtime.CompilerServices.MethodImplAttribute") {
289                                 byte[] data = customBuilder.Data;
290                                 int impla; // the (stupid) ctor takes a short or an int ... 
291                                 impla = (int)data [2];
292                                 impla |= ((int)data [3]) << 8;
293                                 SetImplementationFlags ((MethodImplAttributes)impla);
294                                 return;
295                         }
296                         if (cattrs != null) {
297                                 CustomAttributeBuilder[] new_array = new CustomAttributeBuilder [cattrs.Length + 1];
298                                 cattrs.CopyTo (new_array, 0);
299                                 new_array [cattrs.Length] = customBuilder;
300                                 cattrs = new_array;
301                         } else {
302                                 cattrs = new CustomAttributeBuilder [1];
303                                 cattrs [0] = customBuilder;
304                         }
305                 }
306
307                 [ComVisible (true)]
308                 public void SetCustomAttribute (ConstructorInfo con, byte[] binaryAttribute)
309                 {
310                         if (con == null)
311                                 throw new ArgumentNullException ("con");
312                         if (binaryAttribute == null)
313                                 throw new ArgumentNullException ("binaryAttribute");
314
315                         SetCustomAttribute (new CustomAttributeBuilder (con, binaryAttribute));
316                 }
317
318                 public void SetImplementationFlags (MethodImplAttributes attributes)
319                 {
320                         if (type.is_created)
321                                 throw not_after_created ();
322
323                         iattrs = attributes;
324                 }
325
326                 public Module GetModule ()
327                 {
328                         return type.Module;
329                 }
330
331                 public MethodToken GetToken ()
332                 {
333                         return new MethodToken (0x06000000 | table_idx);
334                 }
335
336                 [MonoTODO]
337                 public void SetSymCustomAttribute (string name, byte[] data)
338                 {
339                         if (type.is_created)
340                                 throw not_after_created ();
341                 }
342
343                 public override Module Module {
344                         get {
345                                 return GetModule ();
346                         }
347                 }
348
349                 public override string ToString ()
350                 {
351                         return "ConstructorBuilder ['" + type.Name + "']";
352                 }
353
354                 internal void fixup ()
355                 {
356                         if (((attrs & (MethodAttributes.Abstract | MethodAttributes.PinvokeImpl)) == 0) && ((iattrs & (MethodImplAttributes.Runtime | MethodImplAttributes.InternalCall)) == 0)) {
357                         if ((ilgen == null) || (ilgen.ILOffset == 0))
358                                 throw new InvalidOperationException ("Method '" + Name + "' does not have a method body.");
359                         }
360                         if (ilgen != null)
361                                 ilgen.label_fixup (this);
362                 }
363                 
364                 internal void GenerateDebugInfo (ISymbolWriter symbolWriter)
365                 {
366                         if (ilgen != null && ilgen.HasDebugInfo) {
367                                 SymbolToken token = new SymbolToken (GetToken().Token);
368                                 symbolWriter.OpenMethod (token);
369                                 symbolWriter.SetSymAttribute (token, "__name", System.Text.Encoding.UTF8.GetBytes (Name));
370                                 ilgen.GenerateDebugInfo (symbolWriter);
371                                 symbolWriter.CloseMethod ();
372                         }
373                 }
374
375                 internal override int get_next_table_index (object obj, int table, bool inc)
376                 {
377                         return type.get_next_table_index (obj, table, inc);
378                 }
379
380                 private void RejectIfCreated ()
381                 {
382                         if (type.is_created)
383                                 throw new InvalidOperationException ("Type definition of the method is complete.");
384                 }
385
386                 private Exception not_supported ()
387                 {
388                         return new NotSupportedException ("The invoked member is not supported in a dynamic module.");
389                 }
390
391                 private Exception not_after_created ()
392                 {
393                         return new InvalidOperationException ("Unable to change after type has been created.");
394                 }
395
396                 private Exception not_created ()
397                 {
398                         return new NotSupportedException ("The type is not yet created.");
399                 }
400
401                 void _ConstructorBuilder.GetIDsOfNames ([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId)
402                 {
403                         throw new NotImplementedException ();
404                 }
405
406                 void _ConstructorBuilder.GetTypeInfo (uint iTInfo, uint lcid, IntPtr ppTInfo)
407                 {
408                         throw new NotImplementedException ();
409                 }
410
411                 void _ConstructorBuilder.GetTypeInfoCount (out uint pcTInfo)
412                 {
413                         throw new NotImplementedException ();
414                 }
415
416                 void _ConstructorBuilder.Invoke (uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr)
417                 {
418                         throw new NotImplementedException ();
419                 }
420         }
421 }
422 #endif