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 protected class GenericInfo {
22 public ArrayList ConstraintList;
25 private PEAPI.TypeAttr attr;
26 private string name_space;
28 private bool is_defined;
29 private bool is_intransit;
30 private BaseClassRef parent;
31 private ArrayList impl_list;
32 private PEAPI.ClassDef classdef;
33 private Hashtable field_table;
34 private ArrayList field_list;
35 private Hashtable method_table;
36 private ArrayList customattr_list;
37 private DeclSecurity decl_sec;
38 private ArrayList event_list;
39 private ArrayList property_list;
40 private GenericParameters gen_params;
41 private ArrayList override_list;
42 private ArrayList override_long_list;
43 private TypeDef outer;
45 private EventDef current_event;
46 private PropertyDef current_property;
51 private bool is_value_class;
52 private bool is_enum_class;
54 public TypeDef (PEAPI.TypeAttr attr, string name_space, string name,
55 BaseClassRef parent, ArrayList impl_list, Location location, GenericParameters gen_params, TypeDef outer)
59 this.impl_list = impl_list;
60 this.gen_params = gen_params;
63 field_table = new Hashtable ();
64 field_list = new ArrayList ();
66 method_table = new Hashtable ();
74 is_value_class = false;
75 is_enum_class = false;
79 int lastdot = name.LastIndexOf ('.');
80 /* Namespace . name split should not be done for nested classes */
81 if (lastdot >= 0 && outer == null) {
82 if (name_space == null || name_space == "")
83 this.name_space = name.Substring (0, lastdot);
85 this.name_space = name_space + "." + name.Substring (0, lastdot);
86 this.name = name.Substring (lastdot + 1);
88 this.name_space = name_space;
97 public string FullName {
98 get { return MakeFullName (); }
101 public string NestedFullName {
102 get { return (outer == null ? FullName : (outer.NestedFullName + "/" + FullName)); }
105 public TypeDef OuterType {
106 get { return outer; }
109 public PEAPI.ClassDef PeapiType {
110 get { return classdef; }
113 public PEAPI.ClassDef ClassDef {
114 get { return classdef; }
117 public bool IsGenericType {
118 get { return (gen_params == null); }
121 public bool IsDefined {
122 get { return is_defined; }
125 public EventDef CurrentEvent {
126 get { return current_event; }
129 public PropertyDef CurrentProperty {
130 get { return current_property; }
133 public bool IsInterface {
134 get { return (attr & PEAPI.TypeAttr.Interface) != 0; }
137 public GenericParameters TypeParameters {
138 get { return gen_params; }
141 public void AddOverride (MethodDef body, BaseTypeRef parent, string name)
143 if (override_list == null)
144 override_list = new ArrayList ();
145 override_list.Add (new DictionaryEntry (body,
146 new DictionaryEntry (parent, name)));
149 public void AddOverride (string sig, BaseMethodRef decl)
151 if (override_long_list == null)
152 override_long_list = new ArrayList ();
153 override_long_list.Add (new DictionaryEntry (sig,
157 public void MakeValueClass ()
159 is_value_class = true;
162 public void MakeEnumClass ()
164 is_enum_class = true;
167 public void SetSize (int size)
172 public void SetPack (int pack)
177 public void AddFieldDef (FieldDef fielddef)
179 if (IsInterface && !fielddef.IsStatic) {
180 Console.WriteLine ("warning -- Non-static field in interface, set to such");
181 fielddef.Attributes |= PEAPI.FieldAttr.Static;
184 field_table.Add (new DictionaryEntry (fielddef.Name, fielddef.Type.FullName), fielddef);
185 field_list.Add (fielddef);
188 public void AddMethodDef (MethodDef methoddef)
190 if (IsInterface && !(methoddef.IsVirtual || methoddef.IsAbstract)) {
191 Console.WriteLine ("warning -- Non-virtual, non-abstract instance method in interface, set to such");
192 methoddef.Attributes |= PEAPI.MethAttr.Abstract | PEAPI.MethAttr.Virtual;
195 method_table.Add (methoddef.Signature, methoddef);
198 public void BeginEventDef (EventDef event_def)
200 if (current_event != null)
201 throw new Exception ("An event definition was not closed.");
203 current_event = event_def;
206 public void EndEventDef ()
208 if (event_list == null)
209 event_list = new ArrayList ();
211 event_list.Add (current_event);
212 current_event = null;
215 public void BeginPropertyDef (PropertyDef property_def)
217 if (current_property != null)
218 throw new Exception ("A property definition was not closed.");
220 current_property = property_def;
223 public void EndPropertyDef ()
225 if (property_list == null)
226 property_list = new ArrayList ();
228 property_list.Add (current_property);
229 current_property = null;
232 public void AddCustomAttribute (CustomAttr customattr)
234 if (customattr_list == null)
235 customattr_list = new ArrayList ();
237 customattr_list.Add (customattr);
240 public void AddPermissionSet (PEAPI.SecurityAction sec_action, PermissionSet ps)
242 if (decl_sec == null)
243 decl_sec = new DeclSecurity ();
245 decl_sec.AddPermissionSet (sec_action, ps);
248 public void AddPermission (PEAPI.SecurityAction sec_action, IPermission iper)
250 if (decl_sec == null)
251 decl_sec = new DeclSecurity ();
253 decl_sec.AddPermission (sec_action, iper);
256 public GenericParameter GetGenericParam (string id)
258 if (gen_params == null)
261 return gen_params.GetGenericParam (id);
264 public GenericParameter GetGenericParam (int index)
266 if (gen_params == null || index < 0 || index >= gen_params.Count)
269 return gen_params [index];
272 public int GetGenericParamNum (string id)
274 if (gen_params == null)
277 return gen_params.GetGenericParamNum (id);
280 /* Resolve any GenParams in constraints, parent & impl_list */
281 private void ResolveGenParams ()
283 if (gen_params == null)
286 gen_params.ResolveConstraints (gen_params, null);
288 BaseGenericTypeRef gtr = parent as BaseGenericTypeRef;
290 gtr.Resolve (gen_params, null);
292 if (impl_list == null)
295 foreach (BaseClassRef impl in impl_list) {
296 gtr = impl as BaseGenericTypeRef;
298 gtr.Resolve (gen_params, null);
302 public void Define (CodeGen code_gen)
308 // Circular definition
309 throw new Exception ("Circular definition of class: " + FullName);
313 PEAPI.TypeAttr vis = attr & PEAPI.TypeAttr.VisibilityMask;
315 if (vis == PEAPI.TypeAttr.Private || vis == PEAPI.TypeAttr.Public) {
316 /* Nested class, but attr not set accordingly. */
317 //FIXME: 'report' warning here
318 Console.WriteLine ("Warning -- Nested class '{0}' has non-nested visibility, set to such.", NestedFullName);
320 attr |= (vis == PEAPI.TypeAttr.Public ? PEAPI.TypeAttr.NestedPublic : PEAPI.TypeAttr.NestedPrivate);
324 if (parent != null) {
326 parent.Resolve (code_gen);
328 is_intransit = false;
329 if (parent.PeapiClass == null) {
330 throw new Exception ("this type can not be a base type: "
334 if (parent.PeapiClass.nameSpace != null &&
335 parent.PeapiClass.nameSpace.CompareTo ("System") == 0) {
337 if (parent.PeapiClass.name.CompareTo ("ValueType") == 0)
338 is_value_class = true;
340 if (parent.PeapiClass.name.CompareTo ("Enum") == 0 )
341 is_enum_class = true;
345 if (!outer.IsDefined)
346 outer.Define (code_gen);
347 classdef = outer.PeapiType.AddNestedClass (attr,
348 name_space, name, parent.PeapiClass);
350 if (is_value_class || is_enum_class) {
351 // Should probably confirm that the parent is System.ValueType
352 classdef = code_gen.PEFile.AddValueClass (attr,
353 name_space, name, is_value_class ? PEAPI.ValueClass.ValueType : PEAPI.ValueClass.Enum);
355 classdef = code_gen.PEFile.AddClass (attr,
356 name_space, name, parent.PeapiClass);
361 if (!outer.IsDefined)
362 outer.Define (code_gen);
363 classdef = outer.PeapiType.AddNestedClass (attr,
366 if (is_value_class || is_enum_class) {
367 classdef = code_gen.PEFile.AddValueClass (attr,
368 name_space, name, is_value_class ? PEAPI.ValueClass.ValueType : PEAPI.ValueClass.Enum);
370 classdef = code_gen.PEFile.AddClass (attr,
374 if (FullName == "System.Object")
375 classdef.SpecialNoSuper ();
380 if (size != -1 || pack != -1)
381 classdef.AddLayoutInfo ( (pack == -1) ? 1 : pack, (size == -1) ? 0 : size);
383 if (impl_list != null) {
384 foreach (BaseClassRef impl in impl_list) {
385 impl.Resolve (code_gen);
386 classdef.AddImplementedInterface (impl.PeapiClass);
390 if (gen_params != null)
391 gen_params.Resolve (code_gen, classdef);
393 is_intransit = false;
395 code_gen.AddToDefineContentsList (this);
398 public void DefineContents (CodeGen code_gen)
400 ArrayList fielddef_list = new ArrayList ();
401 foreach (FieldDef fielddef in field_list) {
402 fielddef.Define (code_gen, classdef);
403 fielddef_list.Add (fielddef.PeapiFieldDef);
406 classdef.SetFieldOrder (fielddef_list);
408 foreach (MethodDef methoddef in method_table.Values) {
409 methoddef.Define (code_gen);
412 if (event_list != null) {
413 foreach (EventDef eventdef in event_list) {
414 eventdef.Define (code_gen, classdef);
418 if (property_list != null) {
419 foreach (PropertyDef propdef in property_list) {
420 propdef.Define (code_gen, classdef);
425 if (customattr_list != null) {
426 foreach (CustomAttr customattr in customattr_list) {
427 customattr.AddTo (code_gen, classdef);
428 if (customattr.IsSuppressUnmanaged (code_gen))
429 classdef.AddAttribute (PEAPI.TypeAttr.HasSecurity);
433 /// Add declarative security to this class
434 if (decl_sec != null) {
435 decl_sec.AddTo (code_gen, classdef);
436 classdef.AddAttribute (PEAPI.TypeAttr.HasSecurity);
439 if (override_list != null) {
440 foreach (DictionaryEntry entry in override_list) {
441 MethodDef body = (MethodDef) entry.Key;
442 DictionaryEntry decl = (DictionaryEntry) entry.Value;
443 BaseTypeRef parent_type = (BaseTypeRef) decl.Key;
444 parent_type.Resolve (code_gen);
445 string over_name = (string) decl.Value;
446 BaseMethodRef over_meth = parent_type.GetMethodRef (body.RetType,
447 body.CallConv, over_name, body.ParamTypeList (), body.GenParamCount);
448 over_meth.Resolve (code_gen);
449 classdef.AddMethodOverride (over_meth.PeapiMethod,
450 body.PeapiMethodDef);
454 if (override_long_list != null) {
455 foreach (DictionaryEntry entry in override_long_list) {
456 string sig = (string) entry.Key;
457 BaseMethodRef decl = (BaseMethodRef) entry.Value;
458 MethodDef body = (MethodDef) method_table[sig];
459 decl.Resolve (code_gen);
460 classdef.AddMethodOverride (decl.PeapiMethod,
461 body.PeapiMethodDef);
466 public PEAPI.MethodDef ResolveMethod (string signature, CodeGen code_gen)
468 MethodDef methoddef = (MethodDef) method_table[signature];
470 if (methoddef == null) {
471 code_gen.Report.Error ("Unable to resolve method: " + signature);
472 Environment.Exit (1);
475 return methoddef.Resolve (code_gen, classdef);
478 public PEAPI.Method ResolveVarargMethod (string signature,
479 CodeGen code_gen, PEAPI.Type[] opt)
481 MethodDef methoddef = (MethodDef) method_table[signature];
483 if (methoddef == null) {
484 code_gen.Report.Error ("Unable to resolve method: " + signature);
485 Environment.Exit (1);
488 methoddef.Resolve (code_gen, classdef);
489 return methoddef.GetVarargSig (opt);
492 public PEAPI.Field ResolveField (string name, string type_name, CodeGen code_gen)
494 FieldDef fielddef = (FieldDef) field_table[new DictionaryEntry (name, type_name)];
496 return fielddef.Resolve (code_gen, classdef);
499 private string MakeFullName ()
501 if (name_space == null || name_space == String.Empty)
504 return name_space + "." + name;
507 public int CompareTo (object obj)
509 TypeDef type_def = (TypeDef) obj;
511 return FullName.CompareTo (type_def.FullName);