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 method_list
;
31 private ArrayList customattr_list
;
32 private DeclSecurity decl_sec
;
33 private ArrayList event_list
;
34 private ArrayList property_list
;
35 private GenericParameters gen_params
;
36 private ArrayList override_list
;
37 private ArrayList override_long_list
;
38 private TypeDef outer
;
40 private EventDef current_event
;
41 private PropertyDef current_property
;
46 private bool is_value_class
;
47 private bool is_enum_class
;
49 private Location location
;
51 public TypeDef (PEAPI
.TypeAttr attr
, string name_space
, string name
,
52 BaseClassRef parent
, ArrayList impl_list
, Location location
, GenericParameters gen_params
, TypeDef outer
)
56 this.impl_list
= impl_list
;
57 this.gen_params
= gen_params
;
59 this.location
= location
;
61 field_table
= new Hashtable ();
62 field_list
= new ArrayList ();
64 method_table
= new Hashtable ();
65 method_list
= new ArrayList ();
73 is_value_class
= false;
74 is_enum_class
= false;
78 int lastdot
= name
.LastIndexOf ('.');
79 /* Namespace . name split should not be done for nested classes */
80 if (lastdot
>= 0 && outer
== null) {
81 if (name_space
== null || name_space
== "")
82 this.name_space
= name
.Substring (0, lastdot
);
84 this.name_space
= name_space
+ "." + name
.Substring (0, lastdot
);
85 this.name
= name
.Substring (lastdot
+ 1);
87 this.name_space
= name_space
;
93 this.attr
|= PEAPI
.TypeAttr
.Abstract
;
100 public string FullName
{
101 get { return MakeFullName (); }
104 public string NestedFullName
{
105 get { return (outer == null ? FullName : (outer.NestedFullName + "/" + FullName)); }
108 public TypeDef OuterType
{
109 get { return outer; }
112 public PEAPI
.ClassDef PeapiType
{
113 get { return classdef; }
116 public PEAPI
.ClassDef ClassDef
{
117 get { return classdef; }
120 public bool IsGenericType
{
121 get { return (gen_params == null); }
124 public bool IsDefined
{
125 get { return is_defined; }
128 public EventDef CurrentEvent
{
129 get { return current_event; }
132 public PropertyDef CurrentProperty
{
133 get { return current_property; }
136 public bool IsInterface
{
137 get { return (attr & PEAPI.TypeAttr.Interface) != 0; }
140 public bool IsAbstract
{
141 get { return (attr & PEAPI.TypeAttr.Abstract) != 0; }
144 public GenericParameters TypeParameters
{
145 get { return gen_params; }
148 public DeclSecurity DeclSecurity
{
150 if (decl_sec
== null)
151 decl_sec
= new DeclSecurity ();
156 public void AddOverride (MethodDef body
, BaseTypeRef parent
, string name
)
158 if (override_list
== null)
159 override_list
= new ArrayList ();
160 override_list
.Add (new DictionaryEntry (body
,
161 new DictionaryEntry (parent
, name
)));
164 public void AddOverride (string sig
, BaseMethodRef decl
)
166 if (override_long_list
== null)
167 override_long_list
= new ArrayList ();
168 override_long_list
.Add (new DictionaryEntry (sig
,
172 public void MakeValueClass ()
174 is_value_class
= true;
177 public void MakeEnumClass ()
179 is_enum_class
= true;
182 public void SetSize (int size
)
187 public void SetPack (int pack
)
192 public void AddFieldDef (FieldDef fielddef
)
194 if (IsInterface
&& !fielddef
.IsStatic
) {
195 Report
.Warning ("Non-static field in interface, set to such");
196 fielddef
.Attributes
|= PEAPI
.FieldAttr
.Static
;
199 DictionaryEntry entry
= new DictionaryEntry (fielddef
.Name
, fielddef
.Type
.FullName
);
200 if (field_table
[entry
] != null)
201 Report
.Error ("Duplicate field declaration: " + fielddef
.Type
.FullName
+ " " + fielddef
.Name
);
202 field_table
.Add (entry
, fielddef
);
203 field_list
.Add (fielddef
);
206 public void AddMethodDef (MethodDef methoddef
)
208 if (IsInterface
&& !methoddef
.IsStatic
&& (!methoddef
.IsVirtual
|| !methoddef
.IsAbstract
)) {
209 Report
.Warning (methoddef
.StartLocation
, "Non-virtual or non-abstract instance method in interface, set to such");
210 methoddef
.Attributes
|= PEAPI
.MethAttr
.Abstract
| PEAPI
.MethAttr
.Virtual
;
213 if (method_table
[methoddef
.Signature
] != null)
214 Report
.Error (methoddef
.StartLocation
, "Duplicate method declaration: " + methoddef
.Signature
);
216 method_table
.Add (methoddef
.Signature
, methoddef
);
217 method_list
.Add (methoddef
);
220 public void BeginEventDef (EventDef event_def
)
222 if (current_event
!= null)
223 Report
.Error ("An event definition was not closed.");
225 current_event
= event_def
;
228 public void EndEventDef ()
230 if (event_list
== null)
231 event_list
= new ArrayList ();
233 event_list
.Add (current_event
);
234 current_event
= null;
237 public void BeginPropertyDef (PropertyDef property_def
)
239 if (current_property
!= null)
240 Report
.Error ("A property definition was not closed.");
242 current_property
= property_def
;
245 public void EndPropertyDef ()
247 if (property_list
== null)
248 property_list
= new ArrayList ();
250 property_list
.Add (current_property
);
251 current_property
= null;
254 public void AddCustomAttribute (CustomAttr customattr
)
256 if (customattr_list
== null)
257 customattr_list
= new ArrayList ();
259 customattr_list
.Add (customattr
);
262 public GenericParameter
GetGenericParam (string id
)
264 if (gen_params
== null)
267 return gen_params
.GetGenericParam (id
);
270 public GenericParameter
GetGenericParam (int index
)
272 if (gen_params
== null || index
< 0 || index
>= gen_params
.Count
)
275 return gen_params
[index
];
278 public int GetGenericParamNum (string id
)
280 if (gen_params
== null)
283 return gen_params
.GetGenericParamNum (id
);
286 /* Resolve any GenParams in constraints, parent & impl_list */
287 private void ResolveGenParams ()
289 if (gen_params
== null)
292 gen_params
.ResolveConstraints (gen_params
, null);
294 BaseGenericTypeRef gtr
= parent
as BaseGenericTypeRef
;
296 gtr
.Resolve (gen_params
, null);
298 if (impl_list
== null)
301 foreach (BaseClassRef impl
in impl_list
) {
302 gtr
= impl
as BaseGenericTypeRef
;
304 gtr
.Resolve (gen_params
, null);
308 private bool IsValueType (string ns
, string name
)
310 return (ns
== "System" && name
== "ValueType");
313 private bool IsEnumType (string ns
, string name
)
315 return (ns
== "System" && name
== "Enum");
318 public void Define (CodeGen code_gen
)
324 // Circular definition
325 Report
.Error ("Circular definition of class: " + FullName
);
329 PEAPI
.TypeAttr vis
= attr
& PEAPI
.TypeAttr
.VisibilityMask
;
331 if (vis
== PEAPI
.TypeAttr
.Private
|| vis
== PEAPI
.TypeAttr
.Public
) {
332 /* Nested class, but attr not set accordingly. */
333 Report
.Warning (location
, String
.Format ("Nested class '{0}' has non-nested visibility, set to such.", NestedFullName
));
335 attr
|= (vis
== PEAPI
.TypeAttr
.Public
? PEAPI
.TypeAttr
.NestedPublic
: PEAPI
.TypeAttr
.NestedPrivate
);
339 if (parent
!= null) {
341 parent
.Resolve (code_gen
);
343 is_intransit
= false;
344 if (parent
.PeapiClass
== null) {
345 Report
.Error ("this type can not be a base type: "
349 if (IsValueType (parent
.PeapiClass
.nameSpace
, parent
.PeapiClass
.name
))
350 is_value_class
= true;
351 else if (IsEnumType (parent
.PeapiClass
.nameSpace
, parent
.PeapiClass
.name
))
352 is_enum_class
= true;
354 if (!IsValueType (name_space
, name
) && !IsEnumType (name_space
, name
) &&
355 is_value_class
&& (attr
& PEAPI
.TypeAttr
.Sealed
) == 0) {
357 Report
.Warning (location
, "Non-sealed value class, made sealed.");
358 attr
|= PEAPI
.TypeAttr
.Sealed
;
362 if (!outer
.IsDefined
)
363 outer
.Define (code_gen
);
364 classdef
= outer
.PeapiType
.AddNestedClass (attr
,
365 name_space
, name
, parent
.PeapiClass
);
367 if (is_value_class
|| is_enum_class
) {
368 // Should probably confirm that the parent is System.ValueType
369 classdef
= code_gen
.PEFile
.AddValueClass (attr
,
370 name_space
, name
, is_value_class
? PEAPI
.ValueClass
.ValueType
: PEAPI
.ValueClass
.Enum
);
372 classdef
= code_gen
.PEFile
.AddClass (attr
,
373 name_space
, name
, parent
.PeapiClass
);
378 if (!outer
.IsDefined
)
379 outer
.Define (code_gen
);
380 classdef
= outer
.PeapiType
.AddNestedClass (attr
,
383 if (is_value_class
|| is_enum_class
) {
384 classdef
= code_gen
.PEFile
.AddValueClass (attr
,
385 name_space
, name
, is_value_class
? PEAPI
.ValueClass
.ValueType
: PEAPI
.ValueClass
.Enum
);
387 classdef
= code_gen
.PEFile
.AddClass (attr
,
391 if (FullName
== "System.Object")
392 classdef
.SpecialNoSuper ();
397 if (size
!= -1 || pack
!= -1)
398 classdef
.AddLayoutInfo ( (pack
== -1) ? 1 : pack
, (size
== -1) ? 0 : size
);
400 if (impl_list
!= null) {
401 foreach (BaseClassRef impl
in impl_list
) {
402 impl
.Resolve (code_gen
);
403 classdef
.AddImplementedInterface (impl
.PeapiClass
);
407 if (gen_params
!= null)
408 gen_params
.Resolve (code_gen
, classdef
);
410 is_intransit
= false;
412 code_gen
.AddToDefineContentsList (this);
415 public void DefineContents (CodeGen code_gen
)
417 ArrayList fielddef_list
= new ArrayList ();
418 foreach (FieldDef fielddef
in field_list
) {
419 fielddef
.Define (code_gen
, classdef
);
420 fielddef_list
.Add (fielddef
.PeapiFieldDef
);
423 classdef
.SetFieldOrder (fielddef_list
);
425 foreach (MethodDef methoddef
in method_list
) {
426 methoddef
.Define (code_gen
);
429 if (event_list
!= null) {
430 foreach (EventDef eventdef
in event_list
) {
431 eventdef
.Define (code_gen
, classdef
);
435 if (property_list
!= null) {
436 foreach (PropertyDef propdef
in property_list
) {
437 propdef
.Define (code_gen
, classdef
);
442 if (customattr_list
!= null) {
443 foreach (CustomAttr customattr
in customattr_list
) {
444 customattr
.AddTo (code_gen
, classdef
);
445 if (customattr
.IsSuppressUnmanaged (code_gen
))
446 classdef
.AddAttribute (PEAPI
.TypeAttr
.HasSecurity
);
450 /// Add declarative security to this class
451 if (decl_sec
!= null) {
452 decl_sec
.AddTo (code_gen
, classdef
);
453 classdef
.AddAttribute (PEAPI
.TypeAttr
.HasSecurity
);
456 if (override_list
!= null) {
457 foreach (DictionaryEntry entry
in override_list
) {
458 MethodDef body
= (MethodDef
) entry
.Key
;
459 DictionaryEntry decl
= (DictionaryEntry
) entry
.Value
;
460 BaseTypeRef parent_type
= (BaseTypeRef
) decl
.Key
;
461 parent_type
.Resolve (code_gen
);
462 string over_name
= (string) decl
.Value
;
463 BaseMethodRef over_meth
= parent_type
.GetMethodRef (body
.RetType
,
464 body
.CallConv
, over_name
, body
.ParamTypeList (), body
.GenParamCount
);
465 over_meth
.Resolve (code_gen
);
466 classdef
.AddMethodOverride (over_meth
.PeapiMethod
,
467 body
.PeapiMethodDef
);
471 if (override_long_list
!= null) {
472 foreach (DictionaryEntry entry
in override_long_list
) {
473 string sig
= (string) entry
.Key
;
474 BaseMethodRef decl
= (BaseMethodRef
) entry
.Value
;
475 MethodDef body
= (MethodDef
) method_table
[sig
];
476 decl
.Resolve (code_gen
);
477 classdef
.AddMethodOverride (decl
.PeapiMethod
,
478 body
.PeapiMethodDef
);
483 public PEAPI
.Method
ResolveMethod (BaseTypeRef ret_type
, PEAPI
.CallConv call_conv
,
484 string name
, BaseTypeRef
[] param
, int gen_param_count
, CodeGen code_gen
)
486 string signature
= MethodDef
.CreateSignature (ret_type
, call_conv
, name
, param
, gen_param_count
, false);
487 MethodDef methoddef
= (MethodDef
) method_table
[signature
];
489 if (methoddef
!= null)
490 return methoddef
.Resolve (code_gen
, classdef
);
491 return ResolveAsMethodRef (ret_type
, call_conv
, name
, param
, gen_param_count
, code_gen
);
494 public PEAPI
.Method
ResolveVarargMethod (BaseTypeRef ret_type
, PEAPI
.CallConv call_conv
,
495 string name
, BaseTypeRef
[] param
, int gen_param_count
, PEAPI
.Type
[] opt
, CodeGen code_gen
)
497 // Only MethodDef sig required to lookup in the method_table
498 string signature
= MethodDef
.CreateSignature (ret_type
, call_conv
, name
, param
, 0, false);
499 MethodDef methoddef
= (MethodDef
) method_table
[signature
];
500 if (methoddef
!= null) {
501 methoddef
.Resolve (code_gen
, classdef
);
502 return methoddef
.GetVarargSig (
504 MethodDef
.CreateSignature (ret_type
, call_conv
, name
, param
, 0, true));
507 return ResolveAsMethodRef (ret_type
, call_conv
, name
, param
, gen_param_count
, code_gen
);
510 private PEAPI
.Method
ResolveAsMethodRef (BaseTypeRef ret_type
, PEAPI
.CallConv call_conv
,
511 string name
, BaseTypeRef
[] param
, int gen_param_count
, CodeGen code_gen
)
513 ExternTypeRef type_ref
= code_gen
.ThisModule
.GetTypeRef (FullName
, false);
514 ExternMethodRef methodref
= (ExternMethodRef
) type_ref
.GetMethodRef (ret_type
, call_conv
, name
, param
, gen_param_count
);
515 methodref
.Resolve (code_gen
);
517 return methodref
.PeapiMethod
;
520 public PEAPI
.Field
ResolveField (string name
, BaseTypeRef ret_type
, CodeGen code_gen
)
522 FieldDef fielddef
= (FieldDef
) field_table
[new DictionaryEntry (name
, ret_type
.FullName
)];
524 return fielddef
.Resolve (code_gen
, classdef
);
526 ExternTypeRef type_ref
= code_gen
.ThisModule
.GetTypeRef (FullName
, false);
527 IFieldRef fieldref
= type_ref
.GetFieldRef (ret_type
, name
);
528 fieldref
.Resolve (code_gen
);
530 return fieldref
.PeapiField
;
533 private string MakeFullName ()
535 if (name_space
== null || name_space
== String
.Empty
)
538 return name_space
+ "." + name
;
541 public int CompareTo (object obj
)
543 TypeDef type_def
= (TypeDef
) obj
;
545 return FullName
.CompareTo (type_def
.FullName
);