[cil-strip] Upgrade to latest Mono.Cecil API
[mono.git] / mcs / tools / cil-strip / Mono.Cecil / MethodDefinition.cs
1 //
2 // MethodDefinition.cs
3 //
4 // Author:
5 //   Jb Evain (jbevain@gmail.com)
6 //
7 // (C) 2005 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 namespace Mono.Cecil {
30
31         using Mono.Cecil.Binary;
32         using Mono.Cecil.Cil;
33
34         internal sealed class MethodDefinition : MethodReference, IMemberDefinition,
35                 IHasSecurity, ICustomAttributeProvider {
36
37                 public const string Cctor = ".cctor";
38                 public const string Ctor = ".ctor";
39
40                 MethodAttributes m_attributes;
41                 MethodImplAttributes m_implAttrs;
42                 MethodSemanticsAttributes m_semAttrs;
43                 SecurityDeclarationCollection m_secDecls;
44                 CustomAttributeCollection m_customAttrs;
45
46                 MethodBody m_body;
47                 RVA m_rva;
48                 OverrideCollection m_overrides;
49                 PInvokeInfo m_pinvoke;
50                 readonly ParameterDefinition m_this;
51
52                 public MethodAttributes Attributes {
53                         get { return m_attributes; }
54                         set { m_attributes = value; }
55                 }
56
57                 public MethodImplAttributes ImplAttributes {
58                         get { return m_implAttrs; }
59                         set { m_implAttrs = value; }
60                 }
61
62                 public MethodSemanticsAttributes SemanticsAttributes {
63                         get { return m_semAttrs; }
64                         set { m_semAttrs = value; }
65                 }
66
67                 public bool HasSecurityDeclarations {
68                         get { return (m_secDecls == null) ? false : (m_secDecls.Count > 0); }
69                 }
70
71                 public SecurityDeclarationCollection SecurityDeclarations {
72                         get {
73                                 if (m_secDecls == null)
74                                         m_secDecls = new SecurityDeclarationCollection (this);
75
76                                 return m_secDecls;
77                         }
78                 }
79
80                 public bool HasCustomAttributes {
81                         get { return (m_customAttrs == null) ? false : (m_customAttrs.Count > 0); }
82                 }
83
84                 public CustomAttributeCollection CustomAttributes {
85                         get {
86                                 if (m_customAttrs == null)
87                                         m_customAttrs = new CustomAttributeCollection (this);
88
89                                 return m_customAttrs;
90                         }
91                 }
92
93                 public RVA RVA {
94                         get { return m_rva; }
95                         set { m_rva = value; }
96                 }
97
98                 public MethodBody Body {
99                         get {
100                                 LoadBody ();
101                                 return m_body;
102                         }
103                         set { m_body = value; }
104                 }
105
106                 public PInvokeInfo PInvokeInfo {
107                         get { return m_pinvoke; }
108                         set { m_pinvoke = value; }
109                 }
110
111                 public bool HasOverrides {
112                         get { return (m_overrides == null) ? false : (m_overrides.Count > 0); }
113                 }
114
115                 public OverrideCollection Overrides {
116                         get {
117                                 if (m_overrides == null)
118                                         m_overrides = new OverrideCollection (this);
119
120                                 return m_overrides;
121                         }
122                 }
123
124                 public ParameterDefinition This {
125                         get { return m_this; }
126                 }
127
128                 #region MethodAttributes
129
130                 public bool IsCompilerControlled {
131                         get { return (m_attributes & MethodAttributes.MemberAccessMask) == MethodAttributes.Compilercontrolled; }
132                         set {
133                                 if (value) {
134                                         m_attributes &= ~MethodAttributes.MemberAccessMask;
135                                         m_attributes |= MethodAttributes.Compilercontrolled;
136                                 } else
137                                         m_attributes &= ~(MethodAttributes.MemberAccessMask & MethodAttributes.Compilercontrolled);
138                         }
139                 }
140
141                 public bool IsPrivate {
142                         get { return (m_attributes & MethodAttributes.MemberAccessMask) == MethodAttributes.Private; }
143                         set {
144                                 if (value) {
145                                         m_attributes &= ~MethodAttributes.MemberAccessMask;
146                                         m_attributes |= MethodAttributes.Private;
147                                 } else
148                                         m_attributes &= ~(MethodAttributes.MemberAccessMask & MethodAttributes.Private);
149                         }
150                 }
151
152                 public bool IsFamilyAndAssembly {
153                         get { return (m_attributes & MethodAttributes.MemberAccessMask) == MethodAttributes.FamANDAssem; }
154                         set {
155                                 if (value) {
156                                         m_attributes &= ~MethodAttributes.MemberAccessMask;
157                                         m_attributes |= MethodAttributes.FamANDAssem;
158                                 } else
159                                         m_attributes &= ~(MethodAttributes.MemberAccessMask & MethodAttributes.FamANDAssem);
160                         }
161                 }
162
163                 public bool IsAssembly {
164                         get { return (m_attributes & MethodAttributes.MemberAccessMask) == MethodAttributes.Assem; }
165                         set {
166                                 if (value) {
167                                         m_attributes &= ~MethodAttributes.MemberAccessMask;
168                                         m_attributes |= MethodAttributes.Assem;
169                                 } else
170                                         m_attributes &= ~(MethodAttributes.MemberAccessMask & MethodAttributes.Assem);
171                         }
172                 }
173
174                 public bool IsFamily {
175                         get { return (m_attributes & MethodAttributes.MemberAccessMask) == MethodAttributes.Family; }
176                         set {
177                                 if (value) {
178                                         m_attributes &= ~MethodAttributes.MemberAccessMask;
179                                         m_attributes |= MethodAttributes.Family;
180                                 } else
181                                         m_attributes &= ~(MethodAttributes.MemberAccessMask & MethodAttributes.Family);
182                         }
183                 }
184
185                 public bool IsFamilyOrAssembly {
186                         get { return (m_attributes & MethodAttributes.MemberAccessMask) == MethodAttributes.FamORAssem; }
187                         set {
188                                 if (value) {
189                                         m_attributes &= ~MethodAttributes.MemberAccessMask;
190                                         m_attributes |= MethodAttributes.FamORAssem;
191                                 } else
192                                         m_attributes &= ~(MethodAttributes.MemberAccessMask & MethodAttributes.FamORAssem);
193                         }
194                 }
195
196                 public bool IsPublic {
197                         get { return (m_attributes & MethodAttributes.MemberAccessMask) == MethodAttributes.Public; }
198                         set {
199                                 if (value) {
200                                         m_attributes &= ~MethodAttributes.MemberAccessMask;
201                                         m_attributes |= MethodAttributes.Public;
202                                 } else
203                                         m_attributes &= ~(MethodAttributes.MemberAccessMask & MethodAttributes.Public);
204                         }
205                 }
206
207                 public bool IsStatic {
208                         get { return (m_attributes & MethodAttributes.Static) != 0; }
209                         set {
210                                 if (value)
211                                         m_attributes |= MethodAttributes.Static;
212                                 else
213                                         m_attributes &= ~MethodAttributes.Static;
214                         }
215                 }
216
217                 public bool IsFinal {
218                         get { return (m_attributes & MethodAttributes.Final) != 0; }
219                         set {
220                                 if (value)
221                                         m_attributes |= MethodAttributes.Final;
222                                 else
223                                         m_attributes &= ~MethodAttributes.Final;
224                         }
225                 }
226
227                 public bool IsVirtual {
228                         get { return (m_attributes & MethodAttributes.Virtual) != 0; }
229                         set {
230                                 if (value)
231                                         m_attributes |= MethodAttributes.Virtual;
232                                 else
233                                         m_attributes &= ~MethodAttributes.Virtual;
234                         }
235                 }
236
237                 public bool IsHideBySig {
238                         get { return (m_attributes & MethodAttributes.HideBySig) != 0; }
239                         set {
240                                 if (value)
241                                         m_attributes |= MethodAttributes.HideBySig;
242                                 else
243                                         m_attributes &= ~MethodAttributes.HideBySig;
244                         }
245                 }
246
247                 public bool IsReuseSlot {
248                         get { return (m_attributes & MethodAttributes.VtableLayoutMask) == MethodAttributes.ReuseSlot; }
249                         set {
250                                 if (value) {
251                                         m_attributes &= ~MethodAttributes.VtableLayoutMask;
252                                         m_attributes |= MethodAttributes.ReuseSlot;
253                                 } else
254                                         m_attributes &= ~(MethodAttributes.VtableLayoutMask & MethodAttributes.ReuseSlot);
255                         }
256                 }
257
258                 public bool IsNewSlot {
259                         get { return (m_attributes & MethodAttributes.VtableLayoutMask) == MethodAttributes.NewSlot; }
260                         set {
261                                 if (value) {
262                                         m_attributes &= ~MethodAttributes.VtableLayoutMask;
263                                         m_attributes |= MethodAttributes.NewSlot;
264                                 } else
265                                         m_attributes &= ~(MethodAttributes.VtableLayoutMask & MethodAttributes.NewSlot);
266                         }
267                 }
268
269                 public bool IsStrict {
270                         get { return (m_attributes & MethodAttributes.Strict) != 0; }
271                         set {
272                                 if (value)
273                                         m_attributes |= MethodAttributes.Strict;
274                                 else
275                                         m_attributes &= ~MethodAttributes.Strict;
276                         }
277                 }
278
279                 public bool IsAbstract {
280                         get { return (m_attributes & MethodAttributes.Abstract) != 0; }
281                         set {
282                                 if (value)
283                                         m_attributes |= MethodAttributes.Abstract;
284                                 else
285                                         m_attributes &= ~MethodAttributes.Abstract;
286                         }
287                 }
288
289                 public bool IsSpecialName {
290                         get { return (m_attributes & MethodAttributes.SpecialName) != 0; }
291                         set {
292                                 if (value)
293                                         m_attributes |= MethodAttributes.SpecialName;
294                                 else
295                                         m_attributes &= ~MethodAttributes.SpecialName;
296                         }
297                 }
298
299                 public bool IsPInvokeImpl {
300                         get { return (m_attributes & MethodAttributes.PInvokeImpl) != 0; }
301                         set {
302                                 if (value)
303                                         m_attributes |= MethodAttributes.PInvokeImpl;
304                                 else
305                                         m_attributes &= ~MethodAttributes.PInvokeImpl;
306                         }
307                 }
308
309                 public bool IsUnmanagedExport {
310                         get { return (m_attributes & MethodAttributes.UnmanagedExport) != 0; }
311                         set {
312                                 if (value)
313                                         m_attributes |= MethodAttributes.UnmanagedExport;
314                                 else
315                                         m_attributes &= ~MethodAttributes.UnmanagedExport;
316                         }
317                 }
318
319                 public bool IsRuntimeSpecialName {
320                         get { return (m_attributes & MethodAttributes.RTSpecialName) != 0; }
321                         set {
322                                 if (value)
323                                         m_attributes |= MethodAttributes.RTSpecialName;
324                                 else
325                                         m_attributes &= ~MethodAttributes.RTSpecialName;
326                         }
327                 }
328
329                 public bool HasSecurity {
330                         get { return (m_attributes & MethodAttributes.HasSecurity) != 0; }
331                         set {
332                                 if (value)
333                                         m_attributes |= MethodAttributes.HasSecurity;
334                                 else
335                                         m_attributes &= ~MethodAttributes.HasSecurity;
336                         }
337                 }
338
339                 #endregion
340
341                 #region MethodImplAttributes
342
343                 public bool IsIL {
344                         get { return (m_implAttrs & MethodImplAttributes.CodeTypeMask) == MethodImplAttributes.IL; }
345                         set {
346                                 if (value) {
347                                         m_implAttrs &= ~MethodImplAttributes.CodeTypeMask;
348                                         m_implAttrs |= MethodImplAttributes.IL;
349                                 } else
350                                         m_implAttrs &= ~(MethodImplAttributes.CodeTypeMask & MethodImplAttributes.IL);
351                         }
352                 }
353
354                 public bool IsNative {
355                         get { return (m_implAttrs & MethodImplAttributes.CodeTypeMask) == MethodImplAttributes.Native; }
356                         set {
357                                 if (value) {
358                                         m_implAttrs &= ~MethodImplAttributes.CodeTypeMask;
359                                         m_implAttrs |= MethodImplAttributes.Native;
360                                 } else
361                                         m_implAttrs &= ~(MethodImplAttributes.CodeTypeMask & MethodImplAttributes.Native);
362                         }
363                 }
364
365                 public bool IsRuntime {
366                         get { return (m_implAttrs & MethodImplAttributes.CodeTypeMask) == MethodImplAttributes.Runtime; }
367                         set {
368                                 if (value) {
369                                         m_implAttrs &= ~MethodImplAttributes.CodeTypeMask;
370                                         m_implAttrs |= MethodImplAttributes.Runtime;
371                                 } else
372                                         m_implAttrs &= ~(MethodImplAttributes.CodeTypeMask & MethodImplAttributes.Runtime);
373                         }
374                 }
375
376                 public bool IsUnmanaged {
377                         get { return (m_implAttrs & MethodImplAttributes.ManagedMask) == MethodImplAttributes.Unmanaged; }
378                         set {
379                                 if (value) {
380                                         m_implAttrs &= ~MethodImplAttributes.ManagedMask;
381                                         m_implAttrs |= MethodImplAttributes.Unmanaged;
382                                 } else
383                                         m_implAttrs &= ~(MethodImplAttributes.ManagedMask & MethodImplAttributes.Unmanaged);
384                         }
385                 }
386
387                 public bool IsManaged {
388                         get { return (m_implAttrs & MethodImplAttributes.ManagedMask) == MethodImplAttributes.Managed; }
389                         set {
390                                 if (value) {
391                                         m_implAttrs &= ~MethodImplAttributes.ManagedMask;
392                                         m_implAttrs |= MethodImplAttributes.Managed;
393                                 } else
394                                         m_implAttrs &= ~(MethodImplAttributes.ManagedMask & MethodImplAttributes.Managed);
395                         }
396                 }
397
398                 public bool IsForwardRef {
399                         get { return (m_implAttrs & MethodImplAttributes.ForwardRef) != 0; }
400                         set {
401                                 if (value)
402                                         m_implAttrs |= MethodImplAttributes.ForwardRef;
403                                 else
404                                         m_implAttrs &= ~MethodImplAttributes.ForwardRef;
405                         }
406                 }
407
408                 public bool IsPreserveSig {
409                         get { return (m_implAttrs & MethodImplAttributes.PreserveSig) != 0; }
410                         set {
411                                 if (value)
412                                         m_implAttrs |= MethodImplAttributes.PreserveSig;
413                                 else
414                                         m_implAttrs &= ~MethodImplAttributes.PreserveSig;
415                         }
416                 }
417
418                 public bool IsInternalCall {
419                         get { return (m_implAttrs & MethodImplAttributes.InternalCall) != 0; }
420                         set {
421                                 if (value)
422                                         m_implAttrs |= MethodImplAttributes.InternalCall;
423                                 else
424                                         m_implAttrs &= ~MethodImplAttributes.InternalCall;
425                         }
426                 }
427
428                 public bool IsSynchronized {
429                         get { return (m_implAttrs & MethodImplAttributes.Synchronized) != 0; }
430                         set {
431                                 if (value)
432                                         m_implAttrs |= MethodImplAttributes.Synchronized;
433                                 else
434                                         m_implAttrs &= ~MethodImplAttributes.Synchronized;
435                         }
436                 }
437
438                 public bool NoInlining {
439                         get { return (m_implAttrs & MethodImplAttributes.NoInlining) != 0; }
440                         set {
441                                 if (value)
442                                         m_implAttrs |= MethodImplAttributes.NoInlining;
443                                 else
444                                         m_implAttrs &= ~MethodImplAttributes.NoInlining;
445                         }
446                 }
447
448                 #endregion
449
450                 #region MethodSemanticsAttributes
451                 public bool IsSetter {
452                         get { return (m_semAttrs & MethodSemanticsAttributes.Setter) != 0; }
453                         set {
454                                 if (value)
455                                         m_semAttrs |= MethodSemanticsAttributes.Setter;
456                                 else
457                                         m_semAttrs &= ~MethodSemanticsAttributes.Setter;
458                         }
459                 }
460
461                 public bool IsGetter {
462                         get { return (m_semAttrs & MethodSemanticsAttributes.Getter) != 0; }
463                         set {
464                                 if (value)
465                                         m_semAttrs |= MethodSemanticsAttributes.Getter;
466                                 else
467                                         m_semAttrs &= ~MethodSemanticsAttributes.Getter;
468                         }
469                 }
470
471                 public bool IsOther {
472                         get { return (m_semAttrs & MethodSemanticsAttributes.Other) != 0; }
473                         set {
474                                 if (value)
475                                         m_semAttrs |= MethodSemanticsAttributes.Other;
476                                 else
477                                         m_semAttrs &= ~MethodSemanticsAttributes.Other;
478                         }
479                 }
480
481                 public bool IsAddOn {
482                         get { return (m_semAttrs & MethodSemanticsAttributes.AddOn) != 0; }
483                         set {
484                                 if (value)
485                                         m_semAttrs |= MethodSemanticsAttributes.AddOn;
486                                 else
487                                         m_semAttrs &= ~MethodSemanticsAttributes.AddOn;
488                         }
489                 }
490
491                 public bool IsRemoveOn {
492                         get { return (m_semAttrs & MethodSemanticsAttributes.RemoveOn) != 0; }
493                         set {
494                                 if (value)
495                                         m_semAttrs |= MethodSemanticsAttributes.RemoveOn;
496                                 else
497                                         m_semAttrs &= ~MethodSemanticsAttributes.RemoveOn;
498                         }
499                 }
500
501                 public bool IsFire {
502                         get { return (m_semAttrs & MethodSemanticsAttributes.Fire) != 0; }
503                         set {
504                                 if (value)
505                                         m_semAttrs |= MethodSemanticsAttributes.Fire;
506                                 else
507                                         m_semAttrs &= ~MethodSemanticsAttributes.Fire;
508                         }
509                 }
510
511                 #endregion
512
513                 public bool IsConstructor {
514                         get {
515                                 return this.IsRuntimeSpecialName && this.IsSpecialName &&
516                                         (this.Name == Cctor || this.Name == Ctor);
517                         }
518                 }
519
520                 public bool HasBody {
521                         get {
522                                 return (m_attributes & MethodAttributes.Abstract) == 0 &&
523                                         (m_attributes & MethodAttributes.PInvokeImpl) == 0 &&
524                                         (m_implAttrs & MethodImplAttributes.InternalCall) == 0 &&
525                                         (m_implAttrs & MethodImplAttributes.Native) == 0 &&
526                                         (m_implAttrs & MethodImplAttributes.Unmanaged) == 0 &&
527                                         (m_implAttrs & MethodImplAttributes.Runtime) == 0;
528                         }
529                 }
530
531                 public new TypeDefinition DeclaringType {
532                         get { return (TypeDefinition) base.DeclaringType; }
533                         set { base.DeclaringType = value; }
534                 }
535
536                 public MethodDefinition (string name, RVA rva,
537                         MethodAttributes attrs, MethodImplAttributes implAttrs,
538                         bool hasThis, bool explicitThis, MethodCallingConvention callConv) :
539                         base (name, hasThis, explicitThis, callConv)
540                 {
541                         m_rva = rva;
542                         m_attributes = attrs;
543                         m_implAttrs = implAttrs;
544
545                         if (!IsStatic)
546                                 m_this = new ParameterDefinition ("this", 0, (ParameterAttributes) 0, null);
547                 }
548
549                 internal MethodDefinition (string name, MethodAttributes attrs) : base (name)
550                 {
551                         m_attributes = attrs;
552
553                         this.HasThis = !this.IsStatic;
554                         if (!IsStatic)
555                                 m_this = new ParameterDefinition ("this", 0, (ParameterAttributes) 0, null);
556                 }
557
558                 public MethodDefinition (string name, MethodAttributes attrs, TypeReference returnType) :
559                         this (name, attrs)
560                 {
561                         this.ReturnType.ReturnType = returnType;
562                 }
563
564                 internal void LoadBody ()
565                 {
566                         if (m_body == null && this.HasBody) {
567                                 m_body = new MethodBody (this);
568
569                                 ModuleDefinition module = DeclaringType != null ? DeclaringType.Module : null;
570
571                                 if (module != null && m_rva != RVA.Zero)
572                                         module.Controller.Reader.Code.VisitMethodBody (m_body);
573                         }
574                 }
575
576                 public override MethodDefinition Resolve ()
577                 {
578                         return this;
579                 }
580
581                 public MethodDefinition Clone ()
582                 {
583                         return Clone (this, new ImportContext (NullReferenceImporter.Instance, this));
584                 }
585
586                 internal static MethodDefinition Clone (MethodDefinition meth, ImportContext context)
587                 {
588                         MethodDefinition nm = new MethodDefinition (
589                                 meth.Name,
590                                 RVA.Zero,
591                                 meth.Attributes,
592                                 meth.ImplAttributes,
593                                 meth.HasThis,
594                                 meth.ExplicitThis,
595                                 meth.CallingConvention);
596
597                         MethodReference contextMethod = context.GenericContext.Method;
598
599                         context.GenericContext.Method = nm;
600
601                         GenericParameter.CloneInto (meth, nm, context);
602
603                         nm.ReturnType.ReturnType = context.Import (meth.ReturnType.ReturnType);
604
605                         if (meth.ReturnType.Parameter != null) {
606                                 nm.ReturnType.Parameter = ParameterDefinition.Clone (meth.ReturnType.Parameter, context);
607                                 nm.ReturnType.Parameter.Method = nm;
608                         }
609
610                         if (meth.PInvokeInfo != null)
611                                 nm.PInvokeInfo = meth.PInvokeInfo; // TODO: import module ?
612
613                         if (meth.HasParameters) {
614                                 foreach (ParameterDefinition param in meth.Parameters)
615                                         nm.Parameters.Add (ParameterDefinition.Clone (param, context));
616                         }
617                         if (meth.HasOverrides) {
618                                 foreach (MethodReference ov in meth.Overrides)
619                                         nm.Overrides.Add (context.Import (ov));
620                         }
621                         if (meth.HasCustomAttributes) {
622                                 foreach (CustomAttribute ca in meth.CustomAttributes)
623                                         nm.CustomAttributes.Add (CustomAttribute.Clone (ca, context));
624                         }
625                         if (meth.HasSecurityDeclarations) {
626                                 foreach (SecurityDeclaration sec in meth.SecurityDeclarations)
627                                         nm.SecurityDeclarations.Add (SecurityDeclaration.Clone (sec));
628                         }
629
630                         if (meth.Body != null)
631                                 nm.Body = MethodBody.Clone (meth.Body, nm, context);
632
633                         context.GenericContext.Method = contextMethod;
634
635                         return nm;
636                 }
637
638                 public override void Accept (IReflectionVisitor visitor)
639                 {
640                         visitor.VisitMethodDefinition (this);
641
642                         this.GenericParameters.Accept (visitor);
643                         this.Parameters.Accept (visitor);
644
645                         if (this.PInvokeInfo != null)
646                                 this.PInvokeInfo.Accept (visitor);
647
648                         this.SecurityDeclarations.Accept (visitor);
649                         this.Overrides.Accept (visitor);
650                         this.CustomAttributes.Accept (visitor);
651                 }
652         }
653 }