5 // Jb Evain (jbevain@gmail.com)
7 // Copyright (c) 2008 - 2010 Jb Evain
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:
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
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.
30 using Mono.Collections.Generic;
32 using RVA = System.UInt32;
34 namespace Mono.Cecil {
36 public sealed class MethodDefinition : MethodReference, IMemberDefinition, ISecurityDeclarationProvider {
39 ushort impl_attributes;
40 internal MethodSemanticsAttributes? sem_attrs;
41 Collection<CustomAttribute> custom_attributes;
42 Collection<SecurityDeclaration> security_declarations;
45 internal PInvokeInfo pinvoke;
46 Collection<MethodReference> overrides;
48 internal MethodBody body;
50 public MethodAttributes Attributes {
51 get { return (MethodAttributes) attributes; }
52 set { attributes = (ushort) value; }
55 public MethodImplAttributes ImplAttributes {
56 get { return (MethodImplAttributes) impl_attributes; }
57 set { impl_attributes = (ushort) value; }
60 public MethodSemanticsAttributes SemanticsAttributes {
62 if (sem_attrs.HasValue)
63 return sem_attrs.Value;
67 return sem_attrs.Value;
70 sem_attrs = MethodSemanticsAttributes.None;
71 return sem_attrs.Value;
73 set { sem_attrs = value; }
76 internal void ReadSemantics ()
78 if (sem_attrs.HasValue)
81 var module = this.Module;
88 module.Read (this, (method, reader) => reader.ReadAllSemantics (method));
91 public bool HasSecurityDeclarations {
93 if (security_declarations != null)
94 return security_declarations.Count > 0;
96 return this.GetHasSecurityDeclarations (Module);
100 public Collection<SecurityDeclaration> SecurityDeclarations {
101 get { return security_declarations ?? (security_declarations = this.GetSecurityDeclarations (Module)); }
104 public bool HasCustomAttributes {
106 if (custom_attributes != null)
107 return custom_attributes.Count > 0;
109 return this.GetHasCustomAttributes (Module);
113 public Collection<CustomAttribute> CustomAttributes {
114 get { return custom_attributes ?? (custom_attributes = this.GetCustomAttributes (Module)); }
118 get { return (int) rva; }
121 public bool HasBody {
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;
132 public MethodBody Body {
140 if (HasImage && rva != 0)
141 return body = Module.Read (this, (method, reader) => reader.ReadMethodBody (method));
143 return body = new MethodBody (this);
145 set { body = value; }
148 public bool HasPInvokeInfo {
153 return IsPInvokeImpl;
157 public PInvokeInfo PInvokeInfo {
162 if (HasImage && IsPInvokeImpl)
163 return pinvoke = Module.Read (this, (method, reader) => reader.ReadPInvokeInfo (method));
168 IsPInvokeImpl = true;
173 public bool HasOverrides {
175 if (overrides != null)
176 return overrides.Count > 0;
179 return Module.Read (this, (method, reader) => reader.HasOverrides (method));
185 public Collection<MethodReference> Overrides {
187 if (overrides != null)
191 return overrides = Module.Read (this, (method, reader) => reader.ReadOverrides (method));
193 return overrides = new Collection<MethodReference> ();
197 public override bool HasGenericParameters {
199 if (generic_parameters != null)
200 return generic_parameters.Count > 0;
202 return this.GetHasGenericParameters (Module);
206 public override Collection<GenericParameter> GenericParameters {
207 get { return generic_parameters ?? (generic_parameters = this.GetGenericParameters (Module)); }
210 #region MethodAttributes
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); }
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); }
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); }
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); }
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); }
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); }
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); }
247 public bool IsStatic {
248 get { return attributes.GetAttributes ((ushort) MethodAttributes.Static); }
249 set { attributes = attributes.SetAttributes ((ushort) MethodAttributes.Static, value); }
252 public bool IsFinal {
253 get { return attributes.GetAttributes ((ushort) MethodAttributes.Final); }
254 set { attributes = attributes.SetAttributes ((ushort) MethodAttributes.Final, value); }
257 public bool IsVirtual {
258 get { return attributes.GetAttributes ((ushort) MethodAttributes.Virtual); }
259 set { attributes = attributes.SetAttributes ((ushort) MethodAttributes.Virtual, value); }
262 public bool IsHideBySig {
263 get { return attributes.GetAttributes ((ushort) MethodAttributes.HideBySig); }
264 set { attributes = attributes.SetAttributes ((ushort) MethodAttributes.HideBySig, value); }
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); }
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); }
277 public bool IsCheckAccessOnOverride {
278 get { return attributes.GetAttributes ((ushort) MethodAttributes.CheckAccessOnOverride); }
279 set { attributes = attributes.SetAttributes ((ushort) MethodAttributes.CheckAccessOnOverride, value); }
282 public bool IsAbstract {
283 get { return attributes.GetAttributes ((ushort) MethodAttributes.Abstract); }
284 set { attributes = attributes.SetAttributes ((ushort) MethodAttributes.Abstract, value); }
287 public bool IsSpecialName {
288 get { return attributes.GetAttributes ((ushort) MethodAttributes.SpecialName); }
289 set { attributes = attributes.SetAttributes ((ushort) MethodAttributes.SpecialName, value); }
292 public bool IsPInvokeImpl {
293 get { return attributes.GetAttributes ((ushort) MethodAttributes.PInvokeImpl); }
294 set { attributes = attributes.SetAttributes ((ushort) MethodAttributes.PInvokeImpl, value); }
297 public bool IsUnmanagedExport {
298 get { return attributes.GetAttributes ((ushort) MethodAttributes.UnmanagedExport); }
299 set { attributes = attributes.SetAttributes ((ushort) MethodAttributes.UnmanagedExport, value); }
302 public bool IsRuntimeSpecialName {
303 get { return attributes.GetAttributes ((ushort) MethodAttributes.RTSpecialName); }
304 set { attributes = attributes.SetAttributes ((ushort) MethodAttributes.RTSpecialName, value); }
307 public bool HasSecurity {
308 get { return attributes.GetAttributes ((ushort) MethodAttributes.HasSecurity); }
309 set { attributes = attributes.SetAttributes ((ushort) MethodAttributes.HasSecurity, value); }
314 #region MethodImplAttributes
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); }
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); }
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); }
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); }
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); }
341 public bool IsForwardRef {
342 get { return impl_attributes.GetAttributes ((ushort) MethodImplAttributes.ForwardRef); }
343 set { impl_attributes = impl_attributes.SetAttributes ((ushort) MethodImplAttributes.ForwardRef, value); }
346 public bool IsPreserveSig {
347 get { return impl_attributes.GetAttributes ((ushort) MethodImplAttributes.PreserveSig); }
348 set { impl_attributes = impl_attributes.SetAttributes ((ushort) MethodImplAttributes.PreserveSig, value); }
351 public bool IsInternalCall {
352 get { return impl_attributes.GetAttributes ((ushort) MethodImplAttributes.InternalCall); }
353 set { impl_attributes = impl_attributes.SetAttributes ((ushort) MethodImplAttributes.InternalCall, value); }
356 public bool IsSynchronized {
357 get { return impl_attributes.GetAttributes ((ushort) MethodImplAttributes.Synchronized); }
358 set { impl_attributes = impl_attributes.SetAttributes ((ushort) MethodImplAttributes.Synchronized, value); }
361 public bool NoInlining {
362 get { return impl_attributes.GetAttributes ((ushort) MethodImplAttributes.NoInlining); }
363 set { impl_attributes = impl_attributes.SetAttributes ((ushort) MethodImplAttributes.NoInlining, value); }
366 public bool NoOptimization {
367 get { return impl_attributes.GetAttributes ((ushort) MethodImplAttributes.NoOptimization); }
368 set { impl_attributes = impl_attributes.SetAttributes ((ushort) MethodImplAttributes.NoOptimization, value); }
373 #region MethodSemanticsAttributes
375 public bool IsSetter {
376 get { return this.GetSemantics (MethodSemanticsAttributes.Setter); }
377 set { this.SetSemantics (MethodSemanticsAttributes.Setter, value); }
380 public bool IsGetter {
381 get { return this.GetSemantics (MethodSemanticsAttributes.Getter); }
382 set { this.SetSemantics (MethodSemanticsAttributes.Getter, value); }
385 public bool IsOther {
386 get { return this.GetSemantics (MethodSemanticsAttributes.Other); }
387 set { this.SetSemantics (MethodSemanticsAttributes.Other, value); }
390 public bool IsAddOn {
391 get { return this.GetSemantics (MethodSemanticsAttributes.AddOn); }
392 set { this.SetSemantics (MethodSemanticsAttributes.AddOn, value); }
395 public bool IsRemoveOn {
396 get { return this.GetSemantics (MethodSemanticsAttributes.RemoveOn); }
397 set { this.SetSemantics (MethodSemanticsAttributes.RemoveOn, value); }
401 get { return this.GetSemantics (MethodSemanticsAttributes.Fire); }
402 set { this.SetSemantics (MethodSemanticsAttributes.Fire, value); }
407 public new TypeDefinition DeclaringType {
408 get { return (TypeDefinition) base.DeclaringType; }
409 set { base.DeclaringType = value; }
412 public bool IsConstructor {
414 return this.IsRuntimeSpecialName
415 && this.IsSpecialName
416 && (this.Name == ".cctor" || this.Name == ".ctor");
420 public override bool IsDefinition {
424 internal MethodDefinition ()
426 this.token = new MetadataToken (TokenType.Method);
429 public MethodDefinition (string name, MethodAttributes attributes, TypeReference returnType)
430 : base (name, returnType)
432 this.attributes = (ushort) attributes;
433 this.HasThis = !this.IsStatic;
434 this.token = new MetadataToken (TokenType.Method);
437 public override MethodDefinition Resolve ()
443 static partial class Mixin {
445 public static ParameterDefinition GetParameter (this MethodBody self, int index)
447 var method = self.method;
449 if (method.HasThis) {
451 return self.ThisParameter;
456 return method.Parameters [index];
459 public static bool GetSemantics (this MethodDefinition self, MethodSemanticsAttributes semantics)
461 return (self.SemanticsAttributes & semantics) != 0;
464 public static void SetSemantics (this MethodDefinition self, MethodSemanticsAttributes semantics, bool value)
467 self.SemanticsAttributes |= semantics;
469 self.SemanticsAttributes &= ~semantics;