/Mono.Cecil/MethodDefinition.cs
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}