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 public TypeDef (PEAPI.TypeAttr attr, string name_space, string name,
49 BaseClassRef parent, ArrayList impl_list, Location location, GenericParameters gen_params, TypeDef outer)
53 this.impl_list = impl_list;
54 this.gen_params = gen_params;
57 field_table = new Hashtable ();
58 field_list = new ArrayList ();
60 method_table = new Hashtable ();
68 is_value_class = false;
69 is_enum_class = false;
73 int lastdot = name.LastIndexOf ('.');
74 /* Namespace . name split should not be done for nested classes */
75 if (lastdot >= 0 && outer == null) {
76 if (name_space == null || name_space == "")
77 this.name_space = name.Substring (0, lastdot);
79 this.name_space = name_space + "." + name.Substring (0, lastdot);
80 this.name = name.Substring (lastdot + 1);
82 this.name_space = name_space;
91 public string FullName {
92 get { return MakeFullName (); }
95 public string NestedFullName {
96 get { return (outer == null ? FullName : (outer.NestedFullName + "/" + FullName)); }
99 public TypeDef OuterType {
100 get { return outer; }
103 public PEAPI.ClassDef PeapiType {
104 get { return classdef; }
107 public PEAPI.ClassDef ClassDef {
108 get { return classdef; }
111 public bool IsGenericType {
112 get { return (gen_params == null); }
115 public bool IsDefined {
116 get { return is_defined; }
119 public EventDef CurrentEvent {
120 get { return current_event; }
123 public PropertyDef CurrentProperty {
124 get { return current_property; }
127 public bool IsInterface {
128 get { return (attr & PEAPI.TypeAttr.Interface) != 0; }
131 public GenericParameters TypeParameters {
132 get { return gen_params; }
135 public DeclSecurity DeclSecurity {
137 if (decl_sec == null)
138 decl_sec = new DeclSecurity ();
143 public void AddOverride (MethodDef body, BaseTypeRef parent, string name)
145 if (override_list == null)
146 override_list = new ArrayList ();
147 override_list.Add (new DictionaryEntry (body,
148 new DictionaryEntry (parent, name)));
151 public void AddOverride (string sig, BaseMethodRef decl)
153 if (override_long_list == null)
154 override_long_list = new ArrayList ();
155 override_long_list.Add (new DictionaryEntry (sig,
159 public void MakeValueClass ()
161 is_value_class = true;
164 public void MakeEnumClass ()
166 is_enum_class = true;
169 public void SetSize (int size)
174 public void SetPack (int pack)
179 public void AddFieldDef (FieldDef fielddef)
181 if (IsInterface && !fielddef.IsStatic) {
182 Console.WriteLine ("warning -- Non-static field in interface, set to such");
183 fielddef.Attributes |= PEAPI.FieldAttr.Static;
186 DictionaryEntry entry = new DictionaryEntry (fielddef.Name, fielddef.Type.FullName);
187 if (field_table [entry] != null)
188 Report.Error ("Duplicate field declaration: " + fielddef.Type.FullName + " " + fielddef.Name);
189 field_table.Add (entry, fielddef);
190 field_list.Add (fielddef);
193 public void AddMethodDef (MethodDef methoddef)
195 if (IsInterface && !(methoddef.IsVirtual || methoddef.IsAbstract)) {
196 Console.WriteLine ("warning -- Non-virtual, non-abstract instance method in interface, set to such");
197 methoddef.Attributes |= PEAPI.MethAttr.Abstract | PEAPI.MethAttr.Virtual;
200 if (method_table [methoddef.Signature] != null)
201 Report.Error ("Duplicate method declaration: " + methoddef.Signature);
203 method_table.Add (methoddef.Signature, methoddef);
206 public void BeginEventDef (EventDef event_def)
208 if (current_event != null)
209 Report.Error ("An event definition was not closed.");
211 current_event = event_def;
214 public void EndEventDef ()
216 if (event_list == null)
217 event_list = new ArrayList ();
219 event_list.Add (current_event);
220 current_event = null;
223 public void BeginPropertyDef (PropertyDef property_def)
225 if (current_property != null)
226 Report.Error ("A property definition was not closed.");
228 current_property = property_def;
231 public void EndPropertyDef ()
233 if (property_list == null)
234 property_list = new ArrayList ();
236 property_list.Add (current_property);
237 current_property = null;
240 public void AddCustomAttribute (CustomAttr customattr)
242 if (customattr_list == null)
243 customattr_list = new ArrayList ();
245 customattr_list.Add (customattr);
248 public GenericParameter GetGenericParam (string id)
250 if (gen_params == null)
253 return gen_params.GetGenericParam (id);
256 public GenericParameter GetGenericParam (int index)
258 if (gen_params == null || index < 0 || index >= gen_params.Count)
261 return gen_params [index];
264 public int GetGenericParamNum (string id)
266 if (gen_params == null)
269 return gen_params.GetGenericParamNum (id);
272 /* Resolve any GenParams in constraints, parent & impl_list */
273 private void ResolveGenParams ()
275 if (gen_params == null)
278 gen_params.ResolveConstraints (gen_params, null);
280 BaseGenericTypeRef gtr = parent as BaseGenericTypeRef;
282 gtr.Resolve (gen_params, null);
284 if (impl_list == null)
287 foreach (BaseClassRef impl in impl_list) {
288 gtr = impl as BaseGenericTypeRef;
290 gtr.Resolve (gen_params, null);
294 public void Define (CodeGen code_gen)
300 // Circular definition
301 Report.Error ("Circular definition of class: " + FullName);
305 PEAPI.TypeAttr vis = attr & PEAPI.TypeAttr.VisibilityMask;
307 if (vis == PEAPI.TypeAttr.Private || vis == PEAPI.TypeAttr.Public) {
308 /* Nested class, but attr not set accordingly. */
309 //FIXME: 'report' warning here
310 Console.WriteLine ("Warning -- Nested class '{0}' has non-nested visibility, set to such.", NestedFullName);
312 attr |= (vis == PEAPI.TypeAttr.Public ? PEAPI.TypeAttr.NestedPublic : PEAPI.TypeAttr.NestedPrivate);
316 if (parent != null) {
318 parent.Resolve (code_gen);
320 is_intransit = false;
321 if (parent.PeapiClass == null) {
322 Report.Error ("this type can not be a base type: "
326 if (parent.PeapiClass.nameSpace != null &&
327 parent.PeapiClass.nameSpace.CompareTo ("System") == 0) {
329 if (parent.PeapiClass.name.CompareTo ("ValueType") == 0)
330 is_value_class = true;
332 if (parent.PeapiClass.name.CompareTo ("Enum") == 0 )
333 is_enum_class = true;
336 if (is_value_class && (attr & PEAPI.TypeAttr.Sealed) == 0) {
337 Console.WriteLine ("Warning -- Non-sealed value class, made sealed.");
338 attr |= PEAPI.TypeAttr.Sealed;
342 if (!outer.IsDefined)
343 outer.Define (code_gen);
344 classdef = outer.PeapiType.AddNestedClass (attr,
345 name_space, name, parent.PeapiClass);
347 if (is_value_class || is_enum_class) {
348 // Should probably confirm that the parent is System.ValueType
349 classdef = code_gen.PEFile.AddValueClass (attr,
350 name_space, name, is_value_class ? PEAPI.ValueClass.ValueType : PEAPI.ValueClass.Enum);
352 classdef = code_gen.PEFile.AddClass (attr,
353 name_space, name, parent.PeapiClass);
358 if (!outer.IsDefined)
359 outer.Define (code_gen);
360 classdef = outer.PeapiType.AddNestedClass (attr,
363 if (is_value_class || is_enum_class) {
364 classdef = code_gen.PEFile.AddValueClass (attr,
365 name_space, name, is_value_class ? PEAPI.ValueClass.ValueType : PEAPI.ValueClass.Enum);
367 classdef = code_gen.PEFile.AddClass (attr,
371 if (FullName == "System.Object")
372 classdef.SpecialNoSuper ();
377 if (size != -1 || pack != -1)
378 classdef.AddLayoutInfo ( (pack == -1) ? 1 : pack, (size == -1) ? 0 : size);
380 if (impl_list != null) {
381 foreach (BaseClassRef impl in impl_list) {
382 impl.Resolve (code_gen);
383 classdef.AddImplementedInterface (impl.PeapiClass);
387 if (gen_params != null)
388 gen_params.Resolve (code_gen, classdef);
390 is_intransit = false;
392 code_gen.AddToDefineContentsList (this);
395 public void DefineContents (CodeGen code_gen)
397 ArrayList fielddef_list = new ArrayList ();
398 foreach (FieldDef fielddef in field_list) {
399 fielddef.Define (code_gen, classdef);
400 fielddef_list.Add (fielddef.PeapiFieldDef);
403 classdef.SetFieldOrder (fielddef_list);
405 foreach (MethodDef methoddef in method_table.Values) {
406 methoddef.Define (code_gen);
409 if (event_list != null) {
410 foreach (EventDef eventdef in event_list) {
411 eventdef.Define (code_gen, classdef);
415 if (property_list != null) {
416 foreach (PropertyDef propdef in property_list) {
417 propdef.Define (code_gen, classdef);
422 if (customattr_list != null) {
423 foreach (CustomAttr customattr in customattr_list) {
424 customattr.AddTo (code_gen, classdef);
425 if (customattr.IsSuppressUnmanaged (code_gen))
426 classdef.AddAttribute (PEAPI.TypeAttr.HasSecurity);
430 /// Add declarative security to this class
431 if (decl_sec != null) {
432 decl_sec.AddTo (code_gen, classdef);
433 classdef.AddAttribute (PEAPI.TypeAttr.HasSecurity);
436 if (override_list != null) {
437 foreach (DictionaryEntry entry in override_list) {
438 MethodDef body = (MethodDef) entry.Key;
439 DictionaryEntry decl = (DictionaryEntry) entry.Value;
440 BaseTypeRef parent_type = (BaseTypeRef) decl.Key;
441 parent_type.Resolve (code_gen);
442 string over_name = (string) decl.Value;
443 BaseMethodRef over_meth = parent_type.GetMethodRef (body.RetType,
444 body.CallConv, over_name, body.ParamTypeList (), body.GenParamCount);
445 over_meth.Resolve (code_gen);
446 classdef.AddMethodOverride (over_meth.PeapiMethod,
447 body.PeapiMethodDef);
451 if (override_long_list != null) {
452 foreach (DictionaryEntry entry in override_long_list) {
453 string sig = (string) entry.Key;
454 BaseMethodRef decl = (BaseMethodRef) entry.Value;
455 MethodDef body = (MethodDef) method_table[sig];
456 decl.Resolve (code_gen);
457 classdef.AddMethodOverride (decl.PeapiMethod,
458 body.PeapiMethodDef);
463 public PEAPI.Method ResolveMethod (BaseTypeRef ret_type, PEAPI.CallConv call_conv,
464 string name, BaseTypeRef [] param, int gen_param_count, CodeGen code_gen)
466 string signature = MethodDef.CreateSignature (ret_type, name, param, gen_param_count);
467 MethodDef methoddef = (MethodDef) method_table[signature];
469 if (methoddef != null)
470 return methoddef.Resolve (code_gen, classdef);
471 return ResolveAsMethodRef (ret_type, call_conv, name, param, gen_param_count, code_gen);
474 public PEAPI.Method ResolveVarargMethod (BaseTypeRef ret_type, PEAPI.CallConv call_conv,
475 string name, BaseTypeRef [] param, int gen_param_count, PEAPI.Type [] opt, CodeGen code_gen)
477 string signature = MethodDef.CreateVarargSignature (ret_type, name, param);
478 MethodDef methoddef = (MethodDef) method_table[signature];
480 if (methoddef != null) {
481 methoddef.Resolve (code_gen, classdef);
482 return methoddef.GetVarargSig (opt);
485 return ResolveAsMethodRef (ret_type, call_conv, name, param, gen_param_count, code_gen);
488 private PEAPI.Method ResolveAsMethodRef (BaseTypeRef ret_type, PEAPI.CallConv call_conv,
489 string name, BaseTypeRef [] param, int gen_param_count, CodeGen code_gen)
491 ExternTypeRef type_ref = code_gen.ThisModule.GetTypeRef (FullName, false);
492 ExternMethodRef methodref = (ExternMethodRef) type_ref.GetMethodRef (ret_type, call_conv, name, param, gen_param_count);
493 methodref.Resolve (code_gen);
495 return methodref.PeapiMethod;
498 public PEAPI.Field ResolveField (string name, BaseTypeRef ret_type, CodeGen code_gen)
500 FieldDef fielddef = (FieldDef) field_table[new DictionaryEntry (name, ret_type.FullName)];
502 return fielddef.Resolve (code_gen, classdef);
504 ExternTypeRef type_ref = code_gen.ThisModule.GetTypeRef (FullName, false);
505 IFieldRef fieldref = type_ref.GetFieldRef (ret_type, name);
506 fieldref.Resolve (code_gen);
508 return fieldref.PeapiField;
511 private string MakeFullName ()
513 if (name_space == null || name_space == String.Empty)
516 return name_space + "." + name;
519 public int CompareTo (object obj)
521 TypeDef type_def = (TypeDef) obj;
523 return FullName.CompareTo (type_def.FullName);