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