PageRenderTime 48ms CodeModel.GetById 2ms app.highlight 39ms RepoModel.GetById 1ms app.codeStats 0ms

/Mono.Cecil/MethodDefinition.cs

http://github.com/jbevain/cecil
C# | 559 lines | 429 code | 120 blank | 10 comment | 68 complexity | 324084a600365f4841cc75a38ff9d147 MD5 | raw file
  1//
  2// Author:
  3//   Jb Evain (jbevain@gmail.com)
  4//
  5// Copyright (c) 2008 - 2015 Jb Evain
  6// Copyright (c) 2008 - 2011 Novell, Inc.
  7//
  8// Licensed under the MIT/X11 license.
  9//
 10
 11using System;
 12using System.Threading;
 13using Mono.Cecil.Cil;
 14using Mono.Collections.Generic;
 15
 16using RVA = System.UInt32;
 17
 18namespace Mono.Cecil {
 19
 20	public sealed class MethodDefinition : MethodReference, IMemberDefinition, ISecurityDeclarationProvider, ICustomDebugInformationProvider {
 21
 22		ushort attributes;
 23		ushort impl_attributes;
 24		internal volatile bool sem_attrs_ready;
 25		internal MethodSemanticsAttributes sem_attrs;
 26		Collection<CustomAttribute> custom_attributes;
 27		Collection<SecurityDeclaration> security_declarations;
 28
 29		internal RVA rva;
 30		internal PInvokeInfo pinvoke;
 31		Collection<MethodReference> overrides;
 32
 33		internal MethodBody body;
 34		internal MethodDebugInformation debug_info;
 35		internal Collection<CustomDebugInformation> custom_infos;
 36
 37		public override string Name {
 38			get { return base.Name; }
 39			set {
 40				if (IsWindowsRuntimeProjection && value != base.Name)
 41					throw new InvalidOperationException ();
 42
 43				base.Name = value;
 44			}
 45		}
 46
 47		public MethodAttributes Attributes {
 48			get { return (MethodAttributes) attributes; }
 49			set {
 50				if (IsWindowsRuntimeProjection && (ushort) value != attributes)
 51					throw new InvalidOperationException ();
 52
 53				attributes = (ushort) value;
 54			}
 55		}
 56
 57		public MethodImplAttributes ImplAttributes {
 58			get { return (MethodImplAttributes) impl_attributes; }
 59			set {
 60				if (IsWindowsRuntimeProjection && (ushort) value != impl_attributes)
 61					throw new InvalidOperationException ();
 62
 63				impl_attributes = (ushort) value;
 64			}
 65		}
 66
 67		public MethodSemanticsAttributes SemanticsAttributes {
 68			get {
 69				if (sem_attrs_ready)
 70					return sem_attrs;
 71
 72				if (HasImage) {
 73					ReadSemantics ();
 74					return sem_attrs;
 75				}
 76
 77				sem_attrs = MethodSemanticsAttributes.None;
 78				sem_attrs_ready = true;
 79				return sem_attrs;
 80			}
 81			set { sem_attrs = value; }
 82		}
 83
 84		internal new MethodDefinitionProjection WindowsRuntimeProjection {
 85			get { return (MethodDefinitionProjection) projection; }
 86			set { projection = value; }
 87		}
 88
 89		internal void ReadSemantics ()
 90		{
 91			if (sem_attrs_ready)
 92				return;
 93
 94			var module = this.Module;
 95			if (module == null)
 96				return;
 97
 98			if (!module.HasImage)
 99				return;
100
101			lock (module.SyncRoot) {
102				if (sem_attrs_ready)
103					return;
104
105				module.Read (this, (method, reader) => reader.ReadAllSemantics (method));
106			}
107		}
108
109		public bool HasSecurityDeclarations {
110			get {
111				if (security_declarations != null)
112					return security_declarations.Count > 0;
113
114				return this.GetHasSecurityDeclarations (Module);
115			}
116		}
117
118		public Collection<SecurityDeclaration> SecurityDeclarations {
119			get { return security_declarations ?? (this.GetSecurityDeclarations (ref security_declarations, Module)); }
120		}
121
122		public bool HasCustomAttributes {
123			get {
124				if (custom_attributes != null)
125					return custom_attributes.Count > 0;
126
127				return this.GetHasCustomAttributes (Module);
128			}
129		}
130
131		public Collection<CustomAttribute> CustomAttributes {
132			get { return custom_attributes ?? (this.GetCustomAttributes (ref custom_attributes, Module)); }
133		}
134
135		public int RVA {
136			get { return (int) rva; }
137		}
138
139		public bool HasBody {
140			get {
141				return (attributes & (ushort) MethodAttributes.Abstract) == 0 &&
142					(attributes & (ushort) MethodAttributes.PInvokeImpl) == 0 &&
143					(impl_attributes & (ushort) MethodImplAttributes.InternalCall) == 0 &&
144					(impl_attributes & (ushort) MethodImplAttributes.Native) == 0 &&
145					(impl_attributes & (ushort) MethodImplAttributes.Unmanaged) == 0 &&
146					(impl_attributes & (ushort) MethodImplAttributes.Runtime) == 0;
147			}
148		}
149
150		public MethodBody Body {
151			get {
152				var local = this.body;
153				if (local != null)
154					return local;
155
156				if (!HasBody)
157					return null;
158
159				if (HasImage && rva != 0)
160					return Module.Read (ref body, this, (method, reader) => reader.ReadMethodBody (method));
161
162				Interlocked.CompareExchange (ref body, new MethodBody (this) , null);
163
164				return body;
165			}
166			set {
167				var module = this.Module;
168				if (module == null) {
169					body = value;
170					return;
171				}
172
173				// we reset Body to null in ILSpy to save memory; so we need that operation to be thread-safe
174				lock (module.SyncRoot) {
175					body = value;
176					if (value == null)
177						this.debug_info = null;
178				}
179			}
180		}
181
182		public MethodDebugInformation DebugInformation {
183			get {
184				Mixin.Read (Body);
185
186				if (debug_info == null) {
187					Interlocked.CompareExchange (ref debug_info, new MethodDebugInformation (this), null);
188				}
189
190				return debug_info;
191			}
192			set {
193				debug_info = value;
194			}
195		}
196
197		public bool HasPInvokeInfo {
198			get {
199				if (pinvoke != null)
200					return true;
201
202				return IsPInvokeImpl;
203			}
204		}
205
206		public PInvokeInfo PInvokeInfo {
207			get {
208				if (pinvoke != null)
209					return pinvoke;
210
211				if (HasImage && IsPInvokeImpl)
212					return Module.Read (ref pinvoke, this, (method, reader) => reader.ReadPInvokeInfo (method));
213
214				return null;
215			}
216			set {
217				IsPInvokeImpl = true;
218				pinvoke = value;
219			}
220		}
221
222		public bool HasOverrides {
223			get {
224				if (overrides != null)
225					return overrides.Count > 0;
226
227				return HasImage && Module.Read (this, (method, reader) => reader.HasOverrides (method));
228			}
229		}
230
231		public Collection<MethodReference> Overrides {
232			get {
233				if (overrides != null)
234					return overrides;
235
236				if (HasImage)
237					return Module.Read (ref overrides, this, (method, reader) => reader.ReadOverrides (method));
238
239				Interlocked.CompareExchange (ref overrides, new Collection<MethodReference> (), null);
240
241				return overrides;
242			}
243		}
244
245		public override bool HasGenericParameters {
246			get {
247				if (generic_parameters != null)
248					return generic_parameters.Count > 0;
249
250				return this.GetHasGenericParameters (Module);
251			}
252		}
253
254		public override Collection<GenericParameter> GenericParameters {
255			get { return generic_parameters ?? (this.GetGenericParameters (ref generic_parameters, Module)); }
256		}
257
258		public bool HasCustomDebugInformations {
259			get {
260				Mixin.Read (Body);
261
262				return !custom_infos.IsNullOrEmpty ();
263			}
264		}
265
266		public Collection<CustomDebugInformation> CustomDebugInformations {
267			get {
268				Mixin.Read (Body);
269
270				if (custom_infos == null)
271					Interlocked.CompareExchange (ref custom_infos, new Collection<CustomDebugInformation> (), null);
272
273				return custom_infos;
274			}
275		}
276
277		#region MethodAttributes
278
279		public bool IsCompilerControlled {
280			get { return attributes.GetMaskedAttributes ((ushort) MethodAttributes.MemberAccessMask, (ushort) MethodAttributes.CompilerControlled); }
281			set { attributes = attributes.SetMaskedAttributes ((ushort) MethodAttributes.MemberAccessMask, (ushort) MethodAttributes.CompilerControlled, value); }
282		}
283
284		public bool IsPrivate {
285			get { return attributes.GetMaskedAttributes ((ushort) MethodAttributes.MemberAccessMask, (ushort) MethodAttributes.Private); }
286			set { attributes = attributes.SetMaskedAttributes ((ushort) MethodAttributes.MemberAccessMask, (ushort) MethodAttributes.Private, value); }
287		}
288
289		public bool IsFamilyAndAssembly {
290			get { return attributes.GetMaskedAttributes ((ushort) MethodAttributes.MemberAccessMask, (ushort) MethodAttributes.FamANDAssem); }
291			set { attributes = attributes.SetMaskedAttributes ((ushort) MethodAttributes.MemberAccessMask, (ushort) MethodAttributes.FamANDAssem, value); }
292		}
293
294		public bool IsAssembly {
295			get { return attributes.GetMaskedAttributes ((ushort) MethodAttributes.MemberAccessMask, (ushort) MethodAttributes.Assembly); }
296			set { attributes = attributes.SetMaskedAttributes ((ushort) MethodAttributes.MemberAccessMask, (ushort) MethodAttributes.Assembly, value); }
297		}
298
299		public bool IsFamily {
300			get { return attributes.GetMaskedAttributes ((ushort) MethodAttributes.MemberAccessMask, (ushort) MethodAttributes.Family); }
301			set { attributes = attributes.SetMaskedAttributes ((ushort) MethodAttributes.MemberAccessMask, (ushort) MethodAttributes.Family, value); }
302		}
303
304		public bool IsFamilyOrAssembly {
305			get { return attributes.GetMaskedAttributes ((ushort) MethodAttributes.MemberAccessMask, (ushort) MethodAttributes.FamORAssem); }
306			set { attributes = attributes.SetMaskedAttributes ((ushort) MethodAttributes.MemberAccessMask, (ushort) MethodAttributes.FamORAssem, value); }
307		}
308
309		public bool IsPublic {
310			get { return attributes.GetMaskedAttributes ((ushort) MethodAttributes.MemberAccessMask, (ushort) MethodAttributes.Public); }
311			set { attributes = attributes.SetMaskedAttributes ((ushort) MethodAttributes.MemberAccessMask, (ushort) MethodAttributes.Public, value); }
312		}
313
314		public bool IsStatic {
315			get { return attributes.GetAttributes ((ushort) MethodAttributes.Static); }
316			set { attributes = attributes.SetAttributes ((ushort) MethodAttributes.Static, value); }
317		}
318
319		public bool IsFinal {
320			get { return attributes.GetAttributes ((ushort) MethodAttributes.Final); }
321			set { attributes = attributes.SetAttributes ((ushort) MethodAttributes.Final, value); }
322		}
323
324		public bool IsVirtual {
325			get { return attributes.GetAttributes ((ushort) MethodAttributes.Virtual); }
326			set { attributes = attributes.SetAttributes ((ushort) MethodAttributes.Virtual, value); }
327		}
328
329		public bool IsHideBySig {
330			get { return attributes.GetAttributes ((ushort) MethodAttributes.HideBySig); }
331			set { attributes = attributes.SetAttributes ((ushort) MethodAttributes.HideBySig, value); }
332		}
333
334		public bool IsReuseSlot {
335			get { return attributes.GetMaskedAttributes ((ushort) MethodAttributes.VtableLayoutMask, (ushort) MethodAttributes.ReuseSlot); }
336			set { attributes = attributes.SetMaskedAttributes ((ushort) MethodAttributes.VtableLayoutMask, (ushort) MethodAttributes.ReuseSlot, value); }
337		}
338
339		public bool IsNewSlot {
340			get { return attributes.GetMaskedAttributes ((ushort) MethodAttributes.VtableLayoutMask, (ushort) MethodAttributes.NewSlot); }
341			set { attributes = attributes.SetMaskedAttributes ((ushort) MethodAttributes.VtableLayoutMask, (ushort) MethodAttributes.NewSlot, value); }
342		}
343
344		public bool IsCheckAccessOnOverride {
345			get { return attributes.GetAttributes ((ushort) MethodAttributes.CheckAccessOnOverride); }
346			set { attributes = attributes.SetAttributes ((ushort) MethodAttributes.CheckAccessOnOverride, value); }
347		}
348
349		public bool IsAbstract {
350			get { return attributes.GetAttributes ((ushort) MethodAttributes.Abstract); }
351			set { attributes = attributes.SetAttributes ((ushort) MethodAttributes.Abstract, value); }
352		}
353
354		public bool IsSpecialName {
355			get { return attributes.GetAttributes ((ushort) MethodAttributes.SpecialName); }
356			set { attributes = attributes.SetAttributes ((ushort) MethodAttributes.SpecialName, value); }
357		}
358
359		public bool IsPInvokeImpl {
360			get { return attributes.GetAttributes ((ushort) MethodAttributes.PInvokeImpl); }
361			set { attributes = attributes.SetAttributes ((ushort) MethodAttributes.PInvokeImpl, value); }
362		}
363
364		public bool IsUnmanagedExport {
365			get { return attributes.GetAttributes ((ushort) MethodAttributes.UnmanagedExport); }
366			set { attributes = attributes.SetAttributes ((ushort) MethodAttributes.UnmanagedExport, value); }
367		}
368
369		public bool IsRuntimeSpecialName {
370			get { return attributes.GetAttributes ((ushort) MethodAttributes.RTSpecialName); }
371			set { attributes = attributes.SetAttributes ((ushort) MethodAttributes.RTSpecialName, value); }
372		}
373
374		public bool HasSecurity {
375			get { return attributes.GetAttributes ((ushort) MethodAttributes.HasSecurity); }
376			set { attributes = attributes.SetAttributes ((ushort) MethodAttributes.HasSecurity, value); }
377		}
378
379		#endregion
380
381		#region MethodImplAttributes
382
383		public bool IsIL {
384			get { return impl_attributes.GetMaskedAttributes ((ushort) MethodImplAttributes.CodeTypeMask, (ushort) MethodImplAttributes.IL); }
385			set { impl_attributes = impl_attributes.SetMaskedAttributes ((ushort) MethodImplAttributes.CodeTypeMask, (ushort) MethodImplAttributes.IL, value); }
386		}
387
388		public bool IsNative {
389			get { return impl_attributes.GetMaskedAttributes ((ushort) MethodImplAttributes.CodeTypeMask, (ushort) MethodImplAttributes.Native); }
390			set { impl_attributes = impl_attributes.SetMaskedAttributes ((ushort) MethodImplAttributes.CodeTypeMask, (ushort) MethodImplAttributes.Native, value); }
391		}
392
393		public bool IsRuntime {
394			get { return impl_attributes.GetMaskedAttributes ((ushort) MethodImplAttributes.CodeTypeMask, (ushort) MethodImplAttributes.Runtime); }
395			set { impl_attributes = impl_attributes.SetMaskedAttributes ((ushort) MethodImplAttributes.CodeTypeMask, (ushort) MethodImplAttributes.Runtime, value); }
396		}
397
398		public bool IsUnmanaged {
399			get { return impl_attributes.GetMaskedAttributes ((ushort) MethodImplAttributes.ManagedMask, (ushort) MethodImplAttributes.Unmanaged); }
400			set { impl_attributes = impl_attributes.SetMaskedAttributes ((ushort) MethodImplAttributes.ManagedMask, (ushort) MethodImplAttributes.Unmanaged, value); }
401		}
402
403		public bool IsManaged {
404			get { return impl_attributes.GetMaskedAttributes ((ushort) MethodImplAttributes.ManagedMask, (ushort) MethodImplAttributes.Managed); }
405			set { impl_attributes = impl_attributes.SetMaskedAttributes ((ushort) MethodImplAttributes.ManagedMask, (ushort) MethodImplAttributes.Managed, value); }
406		}
407
408		public bool IsForwardRef {
409			get { return impl_attributes.GetAttributes ((ushort) MethodImplAttributes.ForwardRef); }
410			set { impl_attributes = impl_attributes.SetAttributes ((ushort) MethodImplAttributes.ForwardRef, value); }
411		}
412
413		public bool IsPreserveSig {
414			get { return impl_attributes.GetAttributes ((ushort) MethodImplAttributes.PreserveSig); }
415			set { impl_attributes = impl_attributes.SetAttributes ((ushort) MethodImplAttributes.PreserveSig, value); }
416		}
417
418		public bool IsInternalCall {
419			get { return impl_attributes.GetAttributes ((ushort) MethodImplAttributes.InternalCall); }
420			set { impl_attributes = impl_attributes.SetAttributes ((ushort) MethodImplAttributes.InternalCall, value); }
421		}
422
423		public bool IsSynchronized {
424			get { return impl_attributes.GetAttributes ((ushort) MethodImplAttributes.Synchronized); }
425			set { impl_attributes = impl_attributes.SetAttributes ((ushort) MethodImplAttributes.Synchronized, value); }
426		}
427
428		public bool NoInlining {
429			get { return impl_attributes.GetAttributes ((ushort) MethodImplAttributes.NoInlining); }
430			set { impl_attributes = impl_attributes.SetAttributes ((ushort) MethodImplAttributes.NoInlining, value); }
431		}
432
433		public bool NoOptimization {
434			get { return impl_attributes.GetAttributes ((ushort) MethodImplAttributes.NoOptimization); }
435			set { impl_attributes = impl_attributes.SetAttributes ((ushort) MethodImplAttributes.NoOptimization, value); }
436		}
437
438		public bool AggressiveInlining {
439			get { return impl_attributes.GetAttributes ((ushort) MethodImplAttributes.AggressiveInlining); }
440			set { impl_attributes = impl_attributes.SetAttributes ((ushort) MethodImplAttributes.AggressiveInlining, value); }
441		}
442
443		#endregion
444
445		#region MethodSemanticsAttributes
446
447		public bool IsSetter {
448			get { return this.GetSemantics (MethodSemanticsAttributes.Setter); }
449			set { this.SetSemantics (MethodSemanticsAttributes.Setter, value); }
450		}
451
452		public bool IsGetter {
453			get { return this.GetSemantics (MethodSemanticsAttributes.Getter); }
454			set { this.SetSemantics (MethodSemanticsAttributes.Getter, value); }
455		}
456
457		public bool IsOther {
458			get { return this.GetSemantics (MethodSemanticsAttributes.Other); }
459			set { this.SetSemantics (MethodSemanticsAttributes.Other, value); }
460		}
461
462		public bool IsAddOn {
463			get { return this.GetSemantics (MethodSemanticsAttributes.AddOn); }
464			set { this.SetSemantics (MethodSemanticsAttributes.AddOn, value); }
465		}
466
467		public bool IsRemoveOn {
468			get { return this.GetSemantics (MethodSemanticsAttributes.RemoveOn); }
469			set { this.SetSemantics (MethodSemanticsAttributes.RemoveOn, value); }
470		}
471
472		public bool IsFire {
473			get { return this.GetSemantics (MethodSemanticsAttributes.Fire); }
474			set { this.SetSemantics (MethodSemanticsAttributes.Fire, value); }
475		}
476
477		#endregion
478
479		public new TypeDefinition DeclaringType {
480			get { return (TypeDefinition) base.DeclaringType; }
481			set { base.DeclaringType = value; }
482		}
483
484		public bool IsConstructor {
485			get {
486				return this.IsRuntimeSpecialName
487					&& this.IsSpecialName
488					&& (this.Name == ".cctor" || this.Name == ".ctor");
489			}
490		}
491
492		public override bool IsDefinition {
493			get { return true; }
494		}
495
496		internal MethodDefinition ()
497		{
498			this.token = new MetadataToken (TokenType.Method);
499		}
500
501		public MethodDefinition (string name, MethodAttributes attributes, TypeReference returnType)
502			: base (name, returnType)
503		{
504			this.attributes = (ushort) attributes;
505			this.HasThis = !this.IsStatic;
506			this.token = new MetadataToken (TokenType.Method);
507		}
508
509		public override MethodDefinition Resolve ()
510		{
511			return this;
512		}
513	}
514
515	static partial class Mixin {
516
517		public static ParameterDefinition GetParameter (this MethodBody self, int index)
518		{
519			var method = self.method;
520
521			if (method.HasThis) {
522				if (index == 0)
523					return self.ThisParameter;
524
525				index--;
526			}
527
528			var parameters = method.Parameters;
529
530			if (index < 0 || index >= parameters.size)
531				return null;
532
533			return parameters [index];
534		}
535
536		public static VariableDefinition GetVariable (this MethodBody self, int index)
537		{
538			var variables = self.Variables;
539
540			if (index < 0 || index >= variables.size)
541				return null;
542
543			return variables [index];
544		}
545
546		public static bool GetSemantics (this MethodDefinition self, MethodSemanticsAttributes semantics)
547		{
548			return (self.SemanticsAttributes & semantics) != 0;
549		}
550
551		public static void SetSemantics (this MethodDefinition self, MethodSemanticsAttributes semantics, bool value)
552		{
553			if (value)
554				self.SemanticsAttributes |= semantics;
555			else
556				self.SemanticsAttributes &= ~semantics;
557		}
558	}
559}