1b2ce9aa758b4ca462a4b6471500140b7fd89997
[mono.git] / mcs / class / Mono.Cecil / Mono.Cecil / MethodDefinition.cs
1 //
2 // MethodDefinition.cs
3 //
4 // Author:
5 //   Jb Evain (jbevain@gmail.com)
6 //
7 // Copyright (c) 2008 - 2010 Jb Evain
8 //
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
16 //
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
19 //
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 //
28
29 using Mono.Cecil.Cil;
30 using Mono.Collections.Generic;
31
32 using RVA = System.UInt32;
33
34 namespace Mono.Cecil {
35
36         public sealed class MethodDefinition : MethodReference, IMemberDefinition, ISecurityDeclarationProvider {
37
38                 ushort attributes;
39                 ushort impl_attributes;
40                 internal MethodSemanticsAttributes? sem_attrs;
41                 Collection<CustomAttribute> custom_attributes;
42                 Collection<SecurityDeclaration> security_declarations;
43
44                 internal RVA rva;
45                 internal PInvokeInfo pinvoke;
46                 Collection<MethodReference> overrides;
47
48                 internal MethodBody body;
49
50                 public MethodAttributes Attributes {
51                         get { return (MethodAttributes) attributes; }
52                         set { attributes = (ushort) value; }
53                 }
54
55                 public MethodImplAttributes ImplAttributes {
56                         get { return (MethodImplAttributes) impl_attributes; }
57                         set { impl_attributes = (ushort) value; }
58                 }
59
60                 public MethodSemanticsAttributes SemanticsAttributes {
61                         get {
62                                 if (sem_attrs.HasValue)
63                                         return sem_attrs.Value;
64
65                                 if (HasImage) {
66                                         ReadSemantics ();
67                                         return sem_attrs.Value;
68                                 }
69
70                                 sem_attrs = MethodSemanticsAttributes.None;
71                                 return sem_attrs.Value;
72                         }
73                         set { sem_attrs = value; }
74                 }
75
76                 internal void ReadSemantics ()
77                 {
78                         if (sem_attrs.HasValue)
79                                 return;
80
81                         var module = this.Module;
82                         if (module == null)
83                                 return;
84
85                         if (!module.HasImage)
86                                 return;
87
88                         module.Read (this, (method, reader) => reader.ReadAllSemantics (method));
89                 }
90
91                 public bool HasSecurityDeclarations {
92                         get {
93                                 if (security_declarations != null)
94                                         return security_declarations.Count > 0;
95
96                                 return this.GetHasSecurityDeclarations (Module);
97                         }
98                 }
99
100                 public Collection<SecurityDeclaration> SecurityDeclarations {
101                         get { return security_declarations ?? (security_declarations = this.GetSecurityDeclarations (Module)); }
102                 }
103
104                 public bool HasCustomAttributes {
105                         get {
106                                 if (custom_attributes != null)
107                                         return custom_attributes.Count > 0;
108
109                                 return this.GetHasCustomAttributes (Module);
110                         }
111                 }
112
113                 public Collection<CustomAttribute> CustomAttributes {
114                         get { return custom_attributes ?? (custom_attributes = this.GetCustomAttributes (Module)); }
115                 }
116
117                 public int RVA {
118                         get { return (int) rva; }
119                 }
120
121                 public bool HasBody {
122                         get {
123                                 return (attributes & (ushort) MethodAttributes.Abstract) == 0 &&
124                                         (attributes & (ushort) MethodAttributes.PInvokeImpl) == 0 &&
125                                         (impl_attributes & (ushort) MethodImplAttributes.InternalCall) == 0 &&
126                                         (impl_attributes & (ushort) MethodImplAttributes.Native) == 0 &&
127                                         (impl_attributes & (ushort) MethodImplAttributes.Unmanaged) == 0 &&
128                                         (impl_attributes & (ushort) MethodImplAttributes.Runtime) == 0;
129                         }
130                 }
131
132                 public MethodBody Body {
133                         get {
134                                 if (body != null)
135                                         return body;
136
137                                 if (!HasBody)
138                                         return null;
139
140                                 if (HasImage && rva != 0)
141                                         return body = Module.Read (this, (method, reader) => reader.ReadMethodBody (method));
142
143                                 return body = new MethodBody (this);
144                         }
145                         set { body = value; }
146                 }
147
148                 public bool HasPInvokeInfo {
149                         get {
150                                 if (pinvoke != null)
151                                         return true;
152
153                                 return IsPInvokeImpl;
154                         }
155                 }
156
157                 public PInvokeInfo PInvokeInfo {
158                         get {
159                                 if (pinvoke != null)
160                                         return pinvoke;
161
162                                 if (HasImage && IsPInvokeImpl)
163                                         return pinvoke = Module.Read (this, (method, reader) => reader.ReadPInvokeInfo (method));
164
165                                 return null;
166                         }
167                         set {
168                                 IsPInvokeImpl = true;
169                                 pinvoke = value;
170                         }
171                 }
172
173                 public bool HasOverrides {
174                         get {
175                                 if (overrides != null)
176                                         return overrides.Count > 0;
177
178                                 if (HasImage)
179                                         return Module.Read (this, (method, reader) => reader.HasOverrides (method));
180
181                                 return false;
182                         }
183                 }
184
185                 public Collection<MethodReference> Overrides {
186                         get {
187                                 if (overrides != null)
188                                         return overrides;
189
190                                 if (HasImage)
191                                         return overrides = Module.Read (this, (method, reader) => reader.ReadOverrides (method));
192
193                                 return overrides = new Collection<MethodReference> ();
194                         }
195                 }
196
197                 public override bool HasGenericParameters {
198                         get {
199                                 if (generic_parameters != null)
200                                         return generic_parameters.Count > 0;
201
202                                 return this.GetHasGenericParameters (Module);
203                         }
204                 }
205
206                 public override Collection<GenericParameter> GenericParameters {
207                         get { return generic_parameters ?? (generic_parameters = this.GetGenericParameters (Module)); }
208                 }
209
210                 #region MethodAttributes
211
212                 public bool IsCompilerControlled {
213                         get { return attributes.GetMaskedAttributes ((ushort) MethodAttributes.MemberAccessMask, (ushort) MethodAttributes.CompilerControlled); }
214                         set { attributes = attributes.SetMaskedAttributes ((ushort) MethodAttributes.MemberAccessMask, (ushort) MethodAttributes.CompilerControlled, value); }
215                 }
216
217                 public bool IsPrivate {
218                         get { return attributes.GetMaskedAttributes ((ushort) MethodAttributes.MemberAccessMask, (ushort) MethodAttributes.Private); }
219                         set { attributes = attributes.SetMaskedAttributes ((ushort) MethodAttributes.MemberAccessMask, (ushort) MethodAttributes.Private, value); }
220                 }
221
222                 public bool IsFamilyAndAssembly {
223                         get { return attributes.GetMaskedAttributes ((ushort) MethodAttributes.MemberAccessMask, (ushort) MethodAttributes.FamANDAssem); }
224                         set { attributes = attributes.SetMaskedAttributes ((ushort) MethodAttributes.MemberAccessMask, (ushort) MethodAttributes.FamANDAssem, value); }
225                 }
226
227                 public bool IsAssembly {
228                         get { return attributes.GetMaskedAttributes ((ushort) MethodAttributes.MemberAccessMask, (ushort) MethodAttributes.Assembly); }
229                         set { attributes = attributes.SetMaskedAttributes ((ushort) MethodAttributes.MemberAccessMask, (ushort) MethodAttributes.Assembly, value); }
230                 }
231
232                 public bool IsFamily {
233                         get { return attributes.GetMaskedAttributes ((ushort) MethodAttributes.MemberAccessMask, (ushort) MethodAttributes.Family); }
234                         set { attributes = attributes.SetMaskedAttributes ((ushort) MethodAttributes.MemberAccessMask, (ushort) MethodAttributes.Family, value); }
235                 }
236
237                 public bool IsFamilyOrAssembly {
238                         get { return attributes.GetMaskedAttributes ((ushort) MethodAttributes.MemberAccessMask, (ushort) MethodAttributes.FamORAssem); }
239                         set { attributes = attributes.SetMaskedAttributes ((ushort) MethodAttributes.MemberAccessMask, (ushort) MethodAttributes.FamORAssem, value); }
240                 }
241
242                 public bool IsPublic {
243                         get { return attributes.GetMaskedAttributes ((ushort) MethodAttributes.MemberAccessMask, (ushort) MethodAttributes.Public); }
244                         set { attributes = attributes.SetMaskedAttributes ((ushort) MethodAttributes.MemberAccessMask, (ushort) MethodAttributes.Public, value); }
245                 }
246
247                 public bool IsStatic {
248                         get { return attributes.GetAttributes ((ushort) MethodAttributes.Static); }
249                         set { attributes = attributes.SetAttributes ((ushort) MethodAttributes.Static, value); }
250                 }
251
252                 public bool IsFinal {
253                         get { return attributes.GetAttributes ((ushort) MethodAttributes.Final); }
254                         set { attributes = attributes.SetAttributes ((ushort) MethodAttributes.Final, value); }
255                 }
256
257                 public bool IsVirtual {
258                         get { return attributes.GetAttributes ((ushort) MethodAttributes.Virtual); }
259                         set { attributes = attributes.SetAttributes ((ushort) MethodAttributes.Virtual, value); }
260                 }
261
262                 public bool IsHideBySig {
263                         get { return attributes.GetAttributes ((ushort) MethodAttributes.HideBySig); }
264                         set { attributes = attributes.SetAttributes ((ushort) MethodAttributes.HideBySig, value); }
265                 }
266
267                 public bool IsReuseSlot {
268                         get { return attributes.GetMaskedAttributes ((ushort) MethodAttributes.VtableLayoutMask, (ushort) MethodAttributes.ReuseSlot); }
269                         set { attributes = attributes.SetMaskedAttributes ((ushort) MethodAttributes.VtableLayoutMask, (ushort) MethodAttributes.ReuseSlot, value); }
270                 }
271
272                 public bool IsNewSlot {
273                         get { return attributes.GetMaskedAttributes ((ushort) MethodAttributes.VtableLayoutMask, (ushort) MethodAttributes.NewSlot); }
274                         set { attributes = attributes.SetMaskedAttributes ((ushort) MethodAttributes.VtableLayoutMask, (ushort) MethodAttributes.NewSlot, value); }
275                 }
276
277                 public bool IsCheckAccessOnOverride {
278                         get { return attributes.GetAttributes ((ushort) MethodAttributes.CheckAccessOnOverride); }
279                         set { attributes = attributes.SetAttributes ((ushort) MethodAttributes.CheckAccessOnOverride, value); }
280                 }
281
282                 public bool IsAbstract {
283                         get { return attributes.GetAttributes ((ushort) MethodAttributes.Abstract); }
284                         set { attributes = attributes.SetAttributes ((ushort) MethodAttributes.Abstract, value); }
285                 }
286
287                 public bool IsSpecialName {
288                         get { return attributes.GetAttributes ((ushort) MethodAttributes.SpecialName); }
289                         set { attributes = attributes.SetAttributes ((ushort) MethodAttributes.SpecialName, value); }
290                 }
291
292                 public bool IsPInvokeImpl {
293                         get { return attributes.GetAttributes ((ushort) MethodAttributes.PInvokeImpl); }
294                         set { attributes = attributes.SetAttributes ((ushort) MethodAttributes.PInvokeImpl, value); }
295                 }
296
297                 public bool IsUnmanagedExport {
298                         get { return attributes.GetAttributes ((ushort) MethodAttributes.UnmanagedExport); }
299                         set { attributes = attributes.SetAttributes ((ushort) MethodAttributes.UnmanagedExport, value); }
300                 }
301
302                 public bool IsRuntimeSpecialName {
303                         get { return attributes.GetAttributes ((ushort) MethodAttributes.RTSpecialName); }
304                         set { attributes = attributes.SetAttributes ((ushort) MethodAttributes.RTSpecialName, value); }
305                 }
306
307                 public bool HasSecurity {
308                         get { return attributes.GetAttributes ((ushort) MethodAttributes.HasSecurity); }
309                         set { attributes = attributes.SetAttributes ((ushort) MethodAttributes.HasSecurity, value); }
310                 }
311
312                 #endregion
313
314                 #region MethodImplAttributes
315
316                 public bool IsIL {
317                         get { return impl_attributes.GetMaskedAttributes ((ushort) MethodImplAttributes.CodeTypeMask, (ushort) MethodImplAttributes.IL); }
318                         set { impl_attributes = impl_attributes.SetMaskedAttributes ((ushort) MethodImplAttributes.CodeTypeMask, (ushort) MethodImplAttributes.IL, value); }
319                 }
320
321                 public bool IsNative {
322                         get { return impl_attributes.GetMaskedAttributes ((ushort) MethodImplAttributes.CodeTypeMask, (ushort) MethodImplAttributes.Native); }
323                         set { impl_attributes = impl_attributes.SetMaskedAttributes ((ushort) MethodImplAttributes.CodeTypeMask, (ushort) MethodImplAttributes.Native, value); }
324                 }
325
326                 public bool IsRuntime {
327                         get { return impl_attributes.GetMaskedAttributes ((ushort) MethodImplAttributes.CodeTypeMask, (ushort) MethodImplAttributes.Runtime); }
328                         set { impl_attributes = impl_attributes.SetMaskedAttributes ((ushort) MethodImplAttributes.CodeTypeMask, (ushort) MethodImplAttributes.Runtime, value); }
329                 }
330
331                 public bool IsUnmanaged {
332                         get { return impl_attributes.GetMaskedAttributes ((ushort) MethodImplAttributes.ManagedMask, (ushort) MethodImplAttributes.Unmanaged); }
333                         set { impl_attributes = impl_attributes.SetMaskedAttributes ((ushort) MethodImplAttributes.ManagedMask, (ushort) MethodImplAttributes.Unmanaged, value); }
334                 }
335
336                 public bool IsManaged {
337                         get { return impl_attributes.GetMaskedAttributes ((ushort) MethodImplAttributes.ManagedMask, (ushort) MethodImplAttributes.Managed); }
338                         set { impl_attributes = impl_attributes.SetMaskedAttributes ((ushort) MethodImplAttributes.ManagedMask, (ushort) MethodImplAttributes.Managed, value); }
339                 }
340
341                 public bool IsForwardRef {
342                         get { return impl_attributes.GetAttributes ((ushort) MethodImplAttributes.ForwardRef); }
343                         set { impl_attributes = impl_attributes.SetAttributes ((ushort) MethodImplAttributes.ForwardRef, value); }
344                 }
345
346                 public bool IsPreserveSig {
347                         get { return impl_attributes.GetAttributes ((ushort) MethodImplAttributes.PreserveSig); }
348                         set { impl_attributes = impl_attributes.SetAttributes ((ushort) MethodImplAttributes.PreserveSig, value); }
349                 }
350
351                 public bool IsInternalCall {
352                         get { return impl_attributes.GetAttributes ((ushort) MethodImplAttributes.InternalCall); }
353                         set { impl_attributes = impl_attributes.SetAttributes ((ushort) MethodImplAttributes.InternalCall, value); }
354                 }
355
356                 public bool IsSynchronized {
357                         get { return impl_attributes.GetAttributes ((ushort) MethodImplAttributes.Synchronized); }
358                         set { impl_attributes = impl_attributes.SetAttributes ((ushort) MethodImplAttributes.Synchronized, value); }
359                 }
360
361                 public bool NoInlining {
362                         get { return impl_attributes.GetAttributes ((ushort) MethodImplAttributes.NoInlining); }
363                         set { impl_attributes = impl_attributes.SetAttributes ((ushort) MethodImplAttributes.NoInlining, value); }
364                 }
365
366                 public bool NoOptimization {
367                         get { return impl_attributes.GetAttributes ((ushort) MethodImplAttributes.NoOptimization); }
368                         set { impl_attributes = impl_attributes.SetAttributes ((ushort) MethodImplAttributes.NoOptimization, value); }
369                 }
370
371                 #endregion
372
373                 #region MethodSemanticsAttributes
374
375                 public bool IsSetter {
376                         get { return this.GetSemantics (MethodSemanticsAttributes.Setter); }
377                         set { this.SetSemantics (MethodSemanticsAttributes.Setter, value); }
378                 }
379
380                 public bool IsGetter {
381                         get { return this.GetSemantics (MethodSemanticsAttributes.Getter); }
382                         set { this.SetSemantics (MethodSemanticsAttributes.Getter, value); }
383                 }
384
385                 public bool IsOther {
386                         get { return this.GetSemantics (MethodSemanticsAttributes.Other); }
387                         set { this.SetSemantics (MethodSemanticsAttributes.Other, value); }
388                 }
389
390                 public bool IsAddOn {
391                         get { return this.GetSemantics (MethodSemanticsAttributes.AddOn); }
392                         set { this.SetSemantics (MethodSemanticsAttributes.AddOn, value); }
393                 }
394
395                 public bool IsRemoveOn {
396                         get { return this.GetSemantics (MethodSemanticsAttributes.RemoveOn); }
397                         set { this.SetSemantics (MethodSemanticsAttributes.RemoveOn, value); }
398                 }
399
400                 public bool IsFire {
401                         get { return this.GetSemantics (MethodSemanticsAttributes.Fire); }
402                         set { this.SetSemantics (MethodSemanticsAttributes.Fire, value); }
403                 }
404
405                 #endregion
406
407                 public new TypeDefinition DeclaringType {
408                         get { return (TypeDefinition) base.DeclaringType; }
409                         set { base.DeclaringType = value; }
410                 }
411
412                 public bool IsConstructor {
413                         get {
414                                 return this.IsRuntimeSpecialName
415                                         && this.IsSpecialName
416                                         && (this.Name == ".cctor" || this.Name == ".ctor");
417                         }
418                 }
419
420                 public override bool IsDefinition {
421                         get { return true; }
422                 }
423
424                 internal MethodDefinition ()
425                 {
426                         this.token = new MetadataToken (TokenType.Method);
427                 }
428
429                 public MethodDefinition (string name, MethodAttributes attributes, TypeReference returnType)
430                         : base (name, returnType)
431                 {
432                         this.attributes = (ushort) attributes;
433                         this.HasThis = !this.IsStatic;
434                         this.token = new MetadataToken (TokenType.Method);
435                 }
436
437                 public override MethodDefinition Resolve ()
438                 {
439                         return this;
440                 }
441         }
442
443         static partial class Mixin {
444
445                 public static ParameterDefinition GetParameter (this MethodBody self, int index)
446                 {
447                         var method = self.method;
448
449                         if (method.HasThis) {
450                                 if (index == 0)
451                                         return self.ThisParameter;
452
453                                 index--;
454                         }
455
456                         return method.Parameters [index];
457                 }
458
459                 public static bool GetSemantics (this MethodDefinition self, MethodSemanticsAttributes semantics)
460                 {
461                         return (self.SemanticsAttributes & semantics) != 0;
462                 }
463
464                 public static void SetSemantics (this MethodDefinition self, MethodSemanticsAttributes semantics, bool value)
465                 {
466                         if (value)
467                                 self.SemanticsAttributes |= semantics;
468                         else
469                                 self.SemanticsAttributes &= ~semantics;
470                 }
471         }
472 }