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 11 using System; 12 13 using Mono.Cecil.Metadata; 14 using Mono.Collections.Generic; 15 16 namespace Mono.Cecil { 17 18 public sealed class TypeDefinition : TypeReference, IMemberDefinition, ISecurityDeclarationProvider { 19 20 uint attributes; 21 TypeReference base_type; 22 internal Range fields_range; 23 internal Range methods_range; 24 25 short packing_size = Mixin.NotResolvedMarker; 26 int class_size = Mixin.NotResolvedMarker; 27 28 InterfaceImplementationCollection interfaces; 29 Collection<TypeDefinition> nested_types; 30 Collection<MethodDefinition> methods; 31 Collection<FieldDefinition> fields; 32 Collection<EventDefinition> events; 33 Collection<PropertyDefinition> properties; 34 Collection<CustomAttribute> custom_attributes; 35 Collection<SecurityDeclaration> security_declarations; 36 37 public TypeAttributes Attributes { 38 get { return (TypeAttributes) attributes; } 39 set { 40 if (IsWindowsRuntimeProjection && (ushort) value != attributes) 41 throw new InvalidOperationException (); 42 43 attributes = (uint) value; 44 } 45 } 46 47 public TypeReference BaseType { 48 get { return base_type; } 49 set { base_type = value; } 50 } 51 52 public override string Name { 53 get { return base.Name; } 54 set { 55 if (IsWindowsRuntimeProjection && value != base.Name) 56 throw new InvalidOperationException (); 57 58 base.Name = value; 59 } 60 } 61 ResolveLayout()62 void ResolveLayout () 63 { 64 if (packing_size != Mixin.NotResolvedMarker || class_size != Mixin.NotResolvedMarker) 65 return; 66 67 if (!HasImage) { 68 packing_size = Mixin.NoDataMarker; 69 class_size = Mixin.NoDataMarker; 70 return; 71 } 72 73 var row = Module.Read (this, (type, reader) => reader.ReadTypeLayout (type)); 74 75 packing_size = row.Col1; 76 class_size = row.Col2; 77 } 78 79 public bool HasLayoutInfo { 80 get { 81 if (packing_size >= 0 || class_size >= 0) 82 return true; 83 84 ResolveLayout (); 85 86 return packing_size >= 0 || class_size >= 0; 87 } 88 } 89 90 public short PackingSize { 91 get { 92 if (packing_size >= 0) 93 return packing_size; 94 95 ResolveLayout (); 96 97 return packing_size >= 0 ? packing_size : (short) -1; 98 } 99 set { packing_size = value; } 100 } 101 102 public int ClassSize { 103 get { 104 if (class_size >= 0) 105 return class_size; 106 107 ResolveLayout (); 108 109 return class_size >= 0 ? class_size : -1; 110 } 111 set { class_size = value; } 112 } 113 114 public bool HasInterfaces { 115 get { 116 if (interfaces != null) 117 return interfaces.Count > 0; 118 119 return HasImage && Module.Read (this, (type, reader) => reader.HasInterfaces (type)); 120 } 121 } 122 123 public Collection<InterfaceImplementation> Interfaces { 124 get { 125 if (interfaces != null) 126 return interfaces; 127 128 if (HasImage) 129 return Module.Read (ref interfaces, this, (type, reader) => reader.ReadInterfaces (type)); 130 131 return interfaces = new InterfaceImplementationCollection (this); 132 } 133 } 134 135 public bool HasNestedTypes { 136 get { 137 if (nested_types != null) 138 return nested_types.Count > 0; 139 140 return HasImage && Module.Read (this, (type, reader) => reader.HasNestedTypes (type)); 141 } 142 } 143 144 public Collection<TypeDefinition> NestedTypes { 145 get { 146 if (nested_types != null) 147 return nested_types; 148 149 if (HasImage) 150 return Module.Read (ref nested_types, this, (type, reader) => reader.ReadNestedTypes (type)); 151 152 return nested_types = new MemberDefinitionCollection<TypeDefinition> (this); 153 } 154 } 155 156 public bool HasMethods { 157 get { 158 if (methods != null) 159 return methods.Count > 0; 160 161 return HasImage && methods_range.Length > 0; 162 } 163 } 164 165 public Collection<MethodDefinition> Methods { 166 get { 167 if (methods != null) 168 return methods; 169 170 if (HasImage) 171 return Module.Read (ref methods, this, (type, reader) => reader.ReadMethods (type)); 172 173 return methods = new MemberDefinitionCollection<MethodDefinition> (this); 174 } 175 } 176 177 public bool HasFields { 178 get { 179 if (fields != null) 180 return fields.Count > 0; 181 182 return HasImage && fields_range.Length > 0; 183 } 184 } 185 186 public Collection<FieldDefinition> Fields { 187 get { 188 if (fields != null) 189 return fields; 190 191 if (HasImage) 192 return Module.Read (ref fields, this, (type, reader) => reader.ReadFields (type)); 193 194 return fields = new MemberDefinitionCollection<FieldDefinition> (this); 195 } 196 } 197 198 public bool HasEvents { 199 get { 200 if (events != null) 201 return events.Count > 0; 202 203 return HasImage && Module.Read (this, (type, reader) => reader.HasEvents (type)); 204 } 205 } 206 207 public Collection<EventDefinition> Events { 208 get { 209 if (events != null) 210 return events; 211 212 if (HasImage) 213 return Module.Read (ref events, this, (type, reader) => reader.ReadEvents (type)); 214 215 return events = new MemberDefinitionCollection<EventDefinition> (this); 216 } 217 } 218 219 public bool HasProperties { 220 get { 221 if (properties != null) 222 return properties.Count > 0; 223 224 return HasImage && Module.Read (this, (type, reader) => reader.HasProperties (type)); 225 } 226 } 227 228 public Collection<PropertyDefinition> Properties { 229 get { 230 if (properties != null) 231 return properties; 232 233 if (HasImage) 234 return Module.Read (ref properties, this, (type, reader) => reader.ReadProperties (type)); 235 236 return properties = new MemberDefinitionCollection<PropertyDefinition> (this); 237 } 238 } 239 240 public bool HasSecurityDeclarations { 241 get { 242 if (security_declarations != null) 243 return security_declarations.Count > 0; 244 245 return this.GetHasSecurityDeclarations (Module); 246 } 247 } 248 249 public Collection<SecurityDeclaration> SecurityDeclarations { 250 get { return security_declarations ?? (this.GetSecurityDeclarations (ref security_declarations, Module)); } 251 } 252 253 public bool HasCustomAttributes { 254 get { 255 if (custom_attributes != null) 256 return custom_attributes.Count > 0; 257 258 return this.GetHasCustomAttributes (Module); 259 } 260 } 261 262 public Collection<CustomAttribute> CustomAttributes { 263 get { return custom_attributes ?? (this.GetCustomAttributes (ref custom_attributes, Module)); } 264 } 265 266 public override bool HasGenericParameters { 267 get { 268 if (generic_parameters != null) 269 return generic_parameters.Count > 0; 270 271 return this.GetHasGenericParameters (Module); 272 } 273 } 274 275 public override Collection<GenericParameter> GenericParameters { 276 get { return generic_parameters ?? (this.GetGenericParameters (ref generic_parameters, Module)); } 277 } 278 279 #region TypeAttributes 280 281 public bool IsNotPublic { 282 get { return attributes.GetMaskedAttributes ((uint) TypeAttributes.VisibilityMask, (uint) TypeAttributes.NotPublic); } 283 set { attributes = attributes.SetMaskedAttributes ((uint) TypeAttributes.VisibilityMask, (uint) TypeAttributes.NotPublic, value); } 284 } 285 286 public bool IsPublic { 287 get { return attributes.GetMaskedAttributes ((uint) TypeAttributes.VisibilityMask, (uint) TypeAttributes.Public); } 288 set { attributes = attributes.SetMaskedAttributes ((uint) TypeAttributes.VisibilityMask, (uint) TypeAttributes.Public, value); } 289 } 290 291 public bool IsNestedPublic { 292 get { return attributes.GetMaskedAttributes ((uint) TypeAttributes.VisibilityMask, (uint) TypeAttributes.NestedPublic); } 293 set { attributes = attributes.SetMaskedAttributes ((uint) TypeAttributes.VisibilityMask, (uint) TypeAttributes.NestedPublic, value); } 294 } 295 296 public bool IsNestedPrivate { 297 get { return attributes.GetMaskedAttributes ((uint) TypeAttributes.VisibilityMask, (uint) TypeAttributes.NestedPrivate); } 298 set { attributes = attributes.SetMaskedAttributes ((uint) TypeAttributes.VisibilityMask, (uint) TypeAttributes.NestedPrivate, value); } 299 } 300 301 public bool IsNestedFamily { 302 get { return attributes.GetMaskedAttributes ((uint) TypeAttributes.VisibilityMask, (uint) TypeAttributes.NestedFamily); } 303 set { attributes = attributes.SetMaskedAttributes ((uint) TypeAttributes.VisibilityMask, (uint) TypeAttributes.NestedFamily, value); } 304 } 305 306 public bool IsNestedAssembly { 307 get { return attributes.GetMaskedAttributes ((uint) TypeAttributes.VisibilityMask, (uint) TypeAttributes.NestedAssembly); } 308 set { attributes = attributes.SetMaskedAttributes ((uint) TypeAttributes.VisibilityMask, (uint) TypeAttributes.NestedAssembly, value); } 309 } 310 311 public bool IsNestedFamilyAndAssembly { 312 get { return attributes.GetMaskedAttributes ((uint) TypeAttributes.VisibilityMask, (uint) TypeAttributes.NestedFamANDAssem); } 313 set { attributes = attributes.SetMaskedAttributes ((uint) TypeAttributes.VisibilityMask, (uint) TypeAttributes.NestedFamANDAssem, value); } 314 } 315 316 public bool IsNestedFamilyOrAssembly { 317 get { return attributes.GetMaskedAttributes ((uint) TypeAttributes.VisibilityMask, (uint) TypeAttributes.NestedFamORAssem); } 318 set { attributes = attributes.SetMaskedAttributes ((uint) TypeAttributes.VisibilityMask, (uint) TypeAttributes.NestedFamORAssem, value); } 319 } 320 321 public bool IsAutoLayout { 322 get { return attributes.GetMaskedAttributes ((uint) TypeAttributes.LayoutMask, (uint) TypeAttributes.AutoLayout); } 323 set { attributes = attributes.SetMaskedAttributes ((uint) TypeAttributes.LayoutMask, (uint) TypeAttributes.AutoLayout, value); } 324 } 325 326 public bool IsSequentialLayout { 327 get { return attributes.GetMaskedAttributes ((uint) TypeAttributes.LayoutMask, (uint) TypeAttributes.SequentialLayout); } 328 set { attributes = attributes.SetMaskedAttributes ((uint) TypeAttributes.LayoutMask, (uint) TypeAttributes.SequentialLayout, value); } 329 } 330 331 public bool IsExplicitLayout { 332 get { return attributes.GetMaskedAttributes ((uint) TypeAttributes.LayoutMask, (uint) TypeAttributes.ExplicitLayout); } 333 set { attributes = attributes.SetMaskedAttributes ((uint) TypeAttributes.LayoutMask, (uint) TypeAttributes.ExplicitLayout, value); } 334 } 335 336 public bool IsClass { 337 get { return attributes.GetMaskedAttributes ((uint) TypeAttributes.ClassSemanticMask, (uint) TypeAttributes.Class); } 338 set { attributes = attributes.SetMaskedAttributes ((uint) TypeAttributes.ClassSemanticMask, (uint) TypeAttributes.Class, value); } 339 } 340 341 public bool IsInterface { 342 get { return attributes.GetMaskedAttributes ((uint) TypeAttributes.ClassSemanticMask, (uint) TypeAttributes.Interface); } 343 set { attributes = attributes.SetMaskedAttributes ((uint) TypeAttributes.ClassSemanticMask, (uint) TypeAttributes.Interface, value); } 344 } 345 346 public bool IsAbstract { 347 get { return attributes.GetAttributes ((uint) TypeAttributes.Abstract); } 348 set { attributes = attributes.SetAttributes ((uint) TypeAttributes.Abstract, value); } 349 } 350 351 public bool IsSealed { 352 get { return attributes.GetAttributes ((uint) TypeAttributes.Sealed); } 353 set { attributes = attributes.SetAttributes ((uint) TypeAttributes.Sealed, value); } 354 } 355 356 public bool IsSpecialName { 357 get { return attributes.GetAttributes ((uint) TypeAttributes.SpecialName); } 358 set { attributes = attributes.SetAttributes ((uint) TypeAttributes.SpecialName, value); } 359 } 360 361 public bool IsImport { 362 get { return attributes.GetAttributes ((uint) TypeAttributes.Import); } 363 set { attributes = attributes.SetAttributes ((uint) TypeAttributes.Import, value); } 364 } 365 366 public bool IsSerializable { 367 get { return attributes.GetAttributes ((uint) TypeAttributes.Serializable); } 368 set { attributes = attributes.SetAttributes ((uint) TypeAttributes.Serializable, value); } 369 } 370 371 public bool IsWindowsRuntime { 372 get { return attributes.GetAttributes ((uint) TypeAttributes.WindowsRuntime); } 373 set { attributes = attributes.SetAttributes ((uint) TypeAttributes.WindowsRuntime, value); } 374 } 375 376 public bool IsAnsiClass { 377 get { return attributes.GetMaskedAttributes ((uint) TypeAttributes.StringFormatMask, (uint) TypeAttributes.AnsiClass); } 378 set { attributes = attributes.SetMaskedAttributes ((uint) TypeAttributes.StringFormatMask, (uint) TypeAttributes.AnsiClass, value); } 379 } 380 381 public bool IsUnicodeClass { 382 get { return attributes.GetMaskedAttributes ((uint) TypeAttributes.StringFormatMask, (uint) TypeAttributes.UnicodeClass); } 383 set { attributes = attributes.SetMaskedAttributes ((uint) TypeAttributes.StringFormatMask, (uint) TypeAttributes.UnicodeClass, value); } 384 } 385 386 public bool IsAutoClass { 387 get { return attributes.GetMaskedAttributes ((uint) TypeAttributes.StringFormatMask, (uint) TypeAttributes.AutoClass); } 388 set { attributes = attributes.SetMaskedAttributes ((uint) TypeAttributes.StringFormatMask, (uint) TypeAttributes.AutoClass, value); } 389 } 390 391 public bool IsBeforeFieldInit { 392 get { return attributes.GetAttributes ((uint) TypeAttributes.BeforeFieldInit); } 393 set { attributes = attributes.SetAttributes ((uint) TypeAttributes.BeforeFieldInit, value); } 394 } 395 396 public bool IsRuntimeSpecialName { 397 get { return attributes.GetAttributes ((uint) TypeAttributes.RTSpecialName); } 398 set { attributes = attributes.SetAttributes ((uint) TypeAttributes.RTSpecialName, value); } 399 } 400 401 public bool HasSecurity { 402 get { return attributes.GetAttributes ((uint) TypeAttributes.HasSecurity); } 403 set { attributes = attributes.SetAttributes ((uint) TypeAttributes.HasSecurity, value); } 404 } 405 406 #endregion 407 408 public bool IsEnum { 409 get { return base_type != null && base_type.IsTypeOf ("System", "Enum"); } 410 } 411 412 public override bool IsValueType { 413 get { 414 if (base_type == null) 415 return false; 416 417 return base_type.IsTypeOf ("System", "Enum") || (base_type.IsTypeOf ("System", "ValueType") && !this.IsTypeOf ("System", "Enum")); 418 } 419 set { 420 throw new NotSupportedException (); 421 } 422 } 423 424 public override bool IsPrimitive { 425 get { 426 ElementType primitive_etype; 427 return MetadataSystem.TryGetPrimitiveElementType (this, out primitive_etype) && primitive_etype.IsPrimitive (); 428 } 429 } 430 431 public override MetadataType MetadataType { 432 get { 433 ElementType primitive_etype; 434 if (MetadataSystem.TryGetPrimitiveElementType (this, out primitive_etype)) 435 return (MetadataType) primitive_etype; 436 437 return base.MetadataType; 438 } 439 } 440 441 public override bool IsDefinition { 442 get { return true; } 443 } 444 445 public new TypeDefinition DeclaringType { 446 get { return (TypeDefinition) base.DeclaringType; } 447 set { base.DeclaringType = value; } 448 } 449 450 internal new TypeDefinitionProjection WindowsRuntimeProjection { 451 get { return (TypeDefinitionProjection) projection; } 452 set { projection = value; } 453 } 454 TypeDefinition(string @namespace, string name, TypeAttributes attributes)455 public TypeDefinition (string @namespace, string name, TypeAttributes attributes) 456 : base (@namespace, name) 457 { 458 this.attributes = (uint) attributes; 459 this.token = new MetadataToken (TokenType.TypeDef); 460 } 461 TypeDefinition(string @namespace, string name, TypeAttributes attributes, TypeReference baseType)462 public TypeDefinition (string @namespace, string name, TypeAttributes attributes, TypeReference baseType) : 463 this (@namespace, name, attributes) 464 { 465 this.BaseType = baseType; 466 } 467 ClearFullName()468 protected override void ClearFullName () 469 { 470 base.ClearFullName (); 471 472 if (!HasNestedTypes) 473 return; 474 475 var nested_types = this.NestedTypes; 476 477 for (int i = 0; i < nested_types.Count; i++) 478 nested_types [i].ClearFullName (); 479 } 480 Resolve()481 public override TypeDefinition Resolve () 482 { 483 return this; 484 } 485 } 486 487 public sealed class InterfaceImplementation : ICustomAttributeProvider 488 { 489 internal TypeDefinition type; 490 internal MetadataToken token; 491 492 TypeReference interface_type; 493 Collection<CustomAttribute> custom_attributes; 494 495 public TypeReference InterfaceType { 496 get { return interface_type; } 497 set { interface_type = value; } 498 } 499 500 public bool HasCustomAttributes { 501 get { 502 if (custom_attributes != null) 503 return custom_attributes.Count > 0; 504 505 if (type == null) 506 return false; 507 508 return this.GetHasCustomAttributes (type.Module); 509 } 510 } 511 512 public Collection<CustomAttribute> CustomAttributes { 513 get { 514 if (type == null) 515 return custom_attributes = new Collection<CustomAttribute> (); 516 517 return custom_attributes ?? (this.GetCustomAttributes (ref custom_attributes, type.Module)); 518 } 519 } 520 521 public MetadataToken MetadataToken { 522 get { return token; } 523 set { token = value; } 524 } 525 InterfaceImplementation(TypeReference interfaceType, MetadataToken token)526 internal InterfaceImplementation (TypeReference interfaceType, MetadataToken token) 527 { 528 this.interface_type = interfaceType; 529 this.token = token; 530 } 531 InterfaceImplementation(TypeReference interfaceType)532 public InterfaceImplementation (TypeReference interfaceType) 533 { 534 Mixin.CheckType (interfaceType, Mixin.Argument.interfaceType); 535 536 this.interface_type = interfaceType; 537 this.token = new MetadataToken (TokenType.InterfaceImpl); 538 } 539 } 540 541 class InterfaceImplementationCollection : Collection<InterfaceImplementation> 542 { 543 readonly TypeDefinition type; 544 InterfaceImplementationCollection(TypeDefinition type)545 internal InterfaceImplementationCollection (TypeDefinition type) 546 { 547 this.type = type; 548 } 549 InterfaceImplementationCollection(TypeDefinition type, int length)550 internal InterfaceImplementationCollection (TypeDefinition type, int length) 551 : base (length) 552 { 553 this.type = type; 554 } 555 OnAdd(InterfaceImplementation item, int index)556 protected override void OnAdd (InterfaceImplementation item, int index) 557 { 558 item.type = type; 559 } 560 OnInsert(InterfaceImplementation item, int index)561 protected override void OnInsert (InterfaceImplementation item, int index) 562 { 563 item.type = type; 564 } 565 OnSet(InterfaceImplementation item, int index)566 protected override void OnSet (InterfaceImplementation item, int index) 567 { 568 item.type = type; 569 } 570 OnRemove(InterfaceImplementation item, int index)571 protected override void OnRemove (InterfaceImplementation item, int index) 572 { 573 item.type = null; 574 } 575 } 576 577 static partial class Mixin { 578 GetEnumUnderlyingType(this TypeDefinition self)579 public static TypeReference GetEnumUnderlyingType (this TypeDefinition self) 580 { 581 var fields = self.Fields; 582 583 for (int i = 0; i < fields.Count; i++) { 584 var field = fields [i]; 585 if (!field.IsStatic) 586 return field.FieldType; 587 } 588 589 throw new ArgumentException (); 590 } 591 GetNestedType(this TypeDefinition self, string fullname)592 public static TypeDefinition GetNestedType (this TypeDefinition self, string fullname) 593 { 594 if (!self.HasNestedTypes) 595 return null; 596 597 var nested_types = self.NestedTypes; 598 599 for (int i = 0; i < nested_types.Count; i++) { 600 var nested_type = nested_types [i]; 601 602 if (nested_type.TypeFullName () == fullname) 603 return nested_type; 604 } 605 606 return null; 607 } 608 } 609 } 610