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