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