5 // Jackson Harper (Jackson@LatitudeGeo.com)
7 // (C) 2003 Jackson Harper, All rights reserved
12 using System.Collections;
13 using System.Security;
15 namespace Mono.ILASM {
17 public class TypeDef : ICustomAttrTarget, IDeclSecurityTarget, IComparable {
19 private PEAPI.TypeAttr attr;
20 private string name_space;
22 private bool is_defined;
23 private bool is_intransit;
24 private BaseClassRef parent;
25 private ArrayList impl_list;
26 private PEAPI.ClassDef classdef;
27 private Hashtable field_table;
28 private ArrayList field_list;
29 private Hashtable method_table;
30 private ArrayList customattr_list;
31 private DeclSecurity decl_sec;
32 private ArrayList event_list;
33 private ArrayList property_list;
34 private GenericParameters gen_params;
35 private ArrayList override_list;
36 private ArrayList override_long_list;
37 private TypeDef outer;
39 private EventDef current_event;
40 private PropertyDef current_property;
45 private bool is_value_class;
46 private bool is_enum_class;
48 private Location location;
50 public TypeDef (PEAPI.TypeAttr attr, string name_space, string name,
51 BaseClassRef parent, ArrayList impl_list, Location location, GenericParameters gen_params, TypeDef outer)
55 this.impl_list = impl_list;
56 this.gen_params = gen_params;
58 this.location = location;
60 field_table = new Hashtable ();
61 field_list = new ArrayList ();
63 method_table = new Hashtable ();
71 is_value_class = false;
72 is_enum_class = false;
76 int lastdot = name.LastIndexOf ('.');
77 /* Namespace . name split should not be done for nested classes */
78 if (lastdot >= 0 && outer == null) {
79 if (name_space == null || name_space == "")
80 this.name_space = name.Substring (0, lastdot);
82 this.name_space = name_space + "." + name.Substring (0, lastdot);
83 this.name = name.Substring (lastdot + 1);
85 this.name_space = name_space;
91 this.attr |= PEAPI.TypeAttr.Abstract;
98 public string FullName {
99 get { return MakeFullName (); }
102 public string NestedFullName {
103 get { return (outer == null ? FullName : (outer.NestedFullName + "/" + FullName)); }
106 public TypeDef OuterType {
107 get { return outer; }
110 public PEAPI.ClassDef PeapiType {
111 get { return classdef; }
114 public PEAPI.ClassDef ClassDef {
115 get { return classdef; }
118 public bool IsGenericType {
119 get { return (gen_params == null); }
122 public bool IsDefined {
123 get { return is_defined; }
126 public EventDef CurrentEvent {
127 get { return current_event; }
130 public PropertyDef CurrentProperty {
131 get { return current_property; }
134 public bool IsInterface {
135 get { return (attr & PEAPI.TypeAttr.Interface) != 0; }
138 public bool IsAbstract {
139 get { return (attr & PEAPI.TypeAttr.Abstract) != 0; }
142 public GenericParameters TypeParameters {
143 get { return gen_params; }
146 public DeclSecurity DeclSecurity {
148 if (decl_sec == null)
149 decl_sec = new DeclSecurity ();
154 public void AddOverride (MethodDef body, BaseTypeRef parent, string name)
156 if (override_list == null)
157 override_list = new ArrayList ();
158 override_list.Add (new DictionaryEntry (body,
159 new DictionaryEntry (parent, name)));
162 public void AddOverride (string sig, BaseMethodRef decl)
164 if (override_long_list == null)
165 override_long_list = new ArrayList ();
166 override_long_list.Add (new DictionaryEntry (sig,
170 public void MakeValueClass ()
172 is_value_class = true;
175 public void MakeEnumClass ()
177 is_enum_class = true;
180 public void SetSize (int size)
185 public void SetPack (int pack)
190 public void AddFieldDef (FieldDef fielddef)
192 if (IsInterface && !fielddef.IsStatic) {
193 Report.Warning ("Non-static field in interface, set to such");
194 fielddef.Attributes |= PEAPI.FieldAttr.Static;
197 DictionaryEntry entry = new DictionaryEntry (fielddef.Name, fielddef.Type.FullName);
198 if (field_table [entry] != null)
199 Report.Error ("Duplicate field declaration: " + fielddef.Type.FullName + " " + fielddef.Name);
200 field_table.Add (entry, fielddef);
201 field_list.Add (fielddef);
204 public void AddMethodDef (MethodDef methoddef)
206 if (IsInterface && !methoddef.IsStatic && (!methoddef.IsVirtual || !methoddef.IsAbstract)) {
207 Report.Warning (methoddef.StartLocation, "Non-virtual or non-abstract instance method in interface, set to such");
208 methoddef.Attributes |= PEAPI.MethAttr.Abstract | PEAPI.MethAttr.Virtual;
211 if (method_table [methoddef.Signature] != null)
212 Report.Error (methoddef.StartLocation, "Duplicate method declaration: " + methoddef.Signature);
214 method_table.Add (methoddef.Signature, methoddef);
217 public void BeginEventDef (EventDef event_def)
219 if (current_event != null)
220 Report.Error ("An event definition was not closed.");
222 current_event = event_def;
225 public void EndEventDef ()
227 if (event_list == null)
228 event_list = new ArrayList ();
230 event_list.Add (current_event);
231 current_event = null;
234 public void BeginPropertyDef (PropertyDef property_def)
236 if (current_property != null)
237 Report.Error ("A property definition was not closed.");
239 current_property = property_def;
242 public void EndPropertyDef ()
244 if (property_list == null)
245 property_list = new ArrayList ();
247 property_list.Add (current_property);
248 current_property = null;
251 public void AddCustomAttribute (CustomAttr customattr)
253 if (customattr_list == null)
254 customattr_list = new ArrayList ();
256 customattr_list.Add (customattr);
259 public GenericParameter GetGenericParam (string id)
261 if (gen_params == null)
264 return gen_params.GetGenericParam (id);
267 public GenericParameter GetGenericParam (int index)
269 if (gen_params == null || index < 0 || index >= gen_params.Count)
272 return gen_params [index];
275 public int GetGenericParamNum (string id)
277 if (gen_params == null)
280 return gen_params.GetGenericParamNum (id);
283 /* Resolve any GenParams in constraints, parent & impl_list */
284 private void ResolveGenParams ()
286 if (gen_params == null)
289 gen_params.ResolveConstraints (gen_params, null);
291 BaseGenericTypeRef gtr = parent as BaseGenericTypeRef;
293 gtr.Resolve (gen_params, null);
295 if (impl_list == null)
298 foreach (BaseClassRef impl in impl_list) {
299 gtr = impl as BaseGenericTypeRef;
301 gtr.Resolve (gen_params, null);
305 private bool IsValueType (string ns, string name)
307 return (ns == "System" && name == "ValueType");
310 private bool IsEnumType (string ns, string name)
312 return (ns == "System" && name == "Enum");
315 public void Define (CodeGen code_gen)
321 // Circular definition
322 Report.Error ("Circular definition of class: " + FullName);
326 PEAPI.TypeAttr vis = attr & PEAPI.TypeAttr.VisibilityMask;
328 if (vis == PEAPI.TypeAttr.Private || vis == PEAPI.TypeAttr.Public) {
329 /* Nested class, but attr not set accordingly. */
330 Report.Warning (location, String.Format ("Nested class '{0}' has non-nested visibility, set to such.", NestedFullName));
332 attr |= (vis == PEAPI.TypeAttr.Public ? PEAPI.TypeAttr.NestedPublic : PEAPI.TypeAttr.NestedPrivate);
336 if (parent != null) {
338 parent.Resolve (code_gen);
340 is_intransit = false;
341 if (parent.PeapiClass == null) {
342 Report.Error ("this type can not be a base type: "
346 if (IsValueType (parent.PeapiClass.nameSpace, parent.PeapiClass.name))
347 is_value_class = true;
348 else if (IsEnumType (parent.PeapiClass.nameSpace, parent.PeapiClass.name))
349 is_enum_class = true;
351 if (!IsValueType (name_space, name) && !IsEnumType (name_space, name) &&
352 is_value_class && (attr & PEAPI.TypeAttr.Sealed) == 0) {
354 Report.Warning (location, "Non-sealed value class, made sealed.");
355 attr |= PEAPI.TypeAttr.Sealed;
359 if (!outer.IsDefined)
360 outer.Define (code_gen);
361 classdef = outer.PeapiType.AddNestedClass (attr,
362 name_space, name, parent.PeapiClass);
364 if (is_value_class || is_enum_class) {
365 // Should probably confirm that the parent is System.ValueType
366 classdef = code_gen.PEFile.AddValueClass (attr,
367 name_space, name, is_value_class ? PEAPI.ValueClass.ValueType : PEAPI.ValueClass.Enum);
369 classdef = code_gen.PEFile.AddClass (attr,
370 name_space, name, parent.PeapiClass);
375 if (!outer.IsDefined)
376 outer.Define (code_gen);
377 classdef = outer.PeapiType.AddNestedClass (attr,
380 if (is_value_class || is_enum_class) {
381 classdef = code_gen.PEFile.AddValueClass (attr,
382 name_space, name, is_value_class ? PEAPI.ValueClass.ValueType : PEAPI.ValueClass.Enum);
384 classdef = code_gen.PEFile.AddClass (attr,
388 if (FullName == "System.Object")
389 classdef.SpecialNoSuper ();
394 if (size != -1 || pack != -1)
395 classdef.AddLayoutInfo ( (pack == -1) ? 1 : pack, (size == -1) ? 0 : size);
397 if (impl_list != null) {
398 foreach (BaseClassRef impl in impl_list) {
399 impl.Resolve (code_gen);
400 classdef.AddImplementedInterface (impl.PeapiClass);
404 if (gen_params != null)
405 gen_params.Resolve (code_gen, classdef);
407 is_intransit = false;
409 code_gen.AddToDefineContentsList (this);
412 public void DefineContents (CodeGen code_gen)
414 ArrayList fielddef_list = new ArrayList ();
415 foreach (FieldDef fielddef in field_list) {
416 fielddef.Define (code_gen, classdef);
417 fielddef_list.Add (fielddef.PeapiFieldDef);
420 classdef.SetFieldOrder (fielddef_list);
422 foreach (MethodDef methoddef in method_table.Values) {
423 methoddef.Define (code_gen);
426 if (event_list != null) {
427 foreach (EventDef eventdef in event_list) {
428 eventdef.Define (code_gen, classdef);
432 if (property_list != null) {
433 foreach (PropertyDef propdef in property_list) {
434 propdef.Define (code_gen, classdef);
439 if (customattr_list != null) {
440 foreach (CustomAttr customattr in customattr_list) {
441 customattr.AddTo (code_gen, classdef);
442 if (customattr.IsSuppressUnmanaged (code_gen))
443 classdef.AddAttribute (PEAPI.TypeAttr.HasSecurity);
447 /// Add declarative security to this class
448 if (decl_sec != null) {
449 decl_sec.AddTo (code_gen, classdef);
450 classdef.AddAttribute (PEAPI.TypeAttr.HasSecurity);
453 if (override_list != null) {
454 foreach (DictionaryEntry entry in override_list) {
455 MethodDef body = (MethodDef) entry.Key;
456 DictionaryEntry decl = (DictionaryEntry) entry.Value;
457 BaseTypeRef parent_type = (BaseTypeRef) decl.Key;
458 parent_type.Resolve (code_gen);
459 string over_name = (string) decl.Value;
460 BaseMethodRef over_meth = parent_type.GetMethodRef (body.RetType,
461 body.CallConv, over_name, body.ParamTypeList (), body.GenParamCount);
462 over_meth.Resolve (code_gen);
463 classdef.AddMethodOverride (over_meth.PeapiMethod,
464 body.PeapiMethodDef);
468 if (override_long_list != null) {
469 foreach (DictionaryEntry entry in override_long_list) {
470 string sig = (string) entry.Key;
471 BaseMethodRef decl = (BaseMethodRef) entry.Value;
472 MethodDef body = (MethodDef) method_table[sig];
473 decl.Resolve (code_gen);
474 classdef.AddMethodOverride (decl.PeapiMethod,
475 body.PeapiMethodDef);
480 public PEAPI.Method ResolveMethod (BaseTypeRef ret_type, PEAPI.CallConv call_conv,
481 string name, BaseTypeRef [] param, int gen_param_count, CodeGen code_gen)
483 string signature = MethodDef.CreateSignature (ret_type, name, param, gen_param_count);
484 MethodDef methoddef = (MethodDef) method_table[signature];
486 if (methoddef != null)
487 return methoddef.Resolve (code_gen, classdef);
488 return ResolveAsMethodRef (ret_type, call_conv, name, param, gen_param_count, code_gen);
491 public PEAPI.Method ResolveVarargMethod (BaseTypeRef ret_type, PEAPI.CallConv call_conv,
492 string name, BaseTypeRef [] param, int gen_param_count, PEAPI.Type [] opt, CodeGen code_gen)
494 string signature = MethodDef.CreateVarargSignature (ret_type, name, param);
495 MethodDef methoddef = (MethodDef) method_table[signature];
497 if (methoddef != null) {
498 methoddef.Resolve (code_gen, classdef);
499 return methoddef.GetVarargSig (opt);
502 return ResolveAsMethodRef (ret_type, call_conv, name, param, gen_param_count, code_gen);
505 private PEAPI.Method ResolveAsMethodRef (BaseTypeRef ret_type, PEAPI.CallConv call_conv,
506 string name, BaseTypeRef [] param, int gen_param_count, CodeGen code_gen)
508 ExternTypeRef type_ref = code_gen.ThisModule.GetTypeRef (FullName, false);
509 ExternMethodRef methodref = (ExternMethodRef) type_ref.GetMethodRef (ret_type, call_conv, name, param, gen_param_count);
510 methodref.Resolve (code_gen);
512 return methodref.PeapiMethod;
515 public PEAPI.Field ResolveField (string name, BaseTypeRef ret_type, CodeGen code_gen)
517 FieldDef fielddef = (FieldDef) field_table[new DictionaryEntry (name, ret_type.FullName)];
519 return fielddef.Resolve (code_gen, classdef);
521 ExternTypeRef type_ref = code_gen.ThisModule.GetTypeRef (FullName, false);
522 IFieldRef fieldref = type_ref.GetFieldRef (ret_type, name);
523 fieldref.Resolve (code_gen);
525 return fieldref.PeapiField;
528 private string MakeFullName ()
530 if (name_space == null || name_space == String.Empty)
533 return name_space + "." + name;
536 public int CompareTo (object obj)
538 TypeDef type_def = (TypeDef) obj;
540 return FullName.CompareTo (type_def.FullName);