2009-08-07 Rodrigo Kumpera <rkumpera@novell.com>
[mono.git] / mcs / mcs / roottypes.cs
1 //
2 // roottypes.cs: keeps a tree representation of the generated code
3 //
4 // Authors: Miguel de Icaza (miguel@gnu.org)
5 //          Marek Safar  (marek.safar@gmail.com)
6 //
7 // Dual licensed under the terms of the MIT X11 or GNU GPL
8 //
9 // Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
10 // Copyright 2003-2008 Novell, Inc.
11 //
12
13 using System;
14 using System.Collections;
15 using System.Reflection;
16 using System.Reflection.Emit;
17 using System.Runtime.InteropServices;
18
19 namespace Mono.CSharp
20 {
21         //
22         // Compiled top-level types
23         //
24         public sealed class ModuleContainer : TypeContainer
25         {
26                 // TODO: It'd be so nice to have generics
27                 Hashtable anonymous_types;
28                 public ModuleBuilder Builder;
29                 bool is_unsafe;
30
31                 bool has_default_charset;
32
33                 public CharSet DefaultCharSet = CharSet.Ansi;
34                 public TypeAttributes DefaultCharSetType = TypeAttributes.AnsiClass;
35
36                 static readonly string[] attribute_targets = new string[] { "module" };
37
38                 public ModuleContainer (bool isUnsafe)
39                         : base (null, null, MemberName.Null, null, Kind.Root)
40                 {
41                         this.is_unsafe = isUnsafe;
42                         types = new ArrayList ();
43                         anonymous_types = new Hashtable ();
44                 }
45
46                 public override AttributeTargets AttributeTargets {
47                         get {
48                                 return AttributeTargets.Module;
49                         }
50                 }
51
52                 public void AddAnonymousType (AnonymousTypeClass type)
53                 {
54                         ArrayList existing = (ArrayList)anonymous_types [type.Parameters.Count];
55                         if (existing == null) {
56                                 existing = new ArrayList ();
57                                 anonymous_types.Add (type.Parameters.Count, existing);
58                         }
59                         existing.Add (type);
60                 }
61
62                 public void AddAttributes (ArrayList attrs)
63                 {
64                         foreach (Attribute a in attrs)
65                                 a.AttachTo (this);
66
67                         if (attributes == null) {
68                                 attributes = new Attributes (attrs);
69                                 return;
70                         }
71
72                         attributes.AddAttributes (attrs);
73                 }
74
75                 public override TypeContainer AddPartial (TypeContainer nextPart)
76                 {
77                         return AddPartial (nextPart, nextPart.Name);
78                 }
79
80                 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa)
81                 {
82                         if (a.Type == pa.CLSCompliant) {
83                                 if (CodeGen.Assembly.ClsCompliantAttribute == null) {
84                                         Report.Warning (3012, 1, a.Location, "You must specify the CLSCompliant attribute on the assembly, not the module, to enable CLS compliance checking");
85                                 } else if (CodeGen.Assembly.IsClsCompliant != a.GetBoolean ()) {
86                                         Report.SymbolRelatedToPreviousError (CodeGen.Assembly.ClsCompliantAttribute.Location, CodeGen.Assembly.ClsCompliantAttribute.GetSignatureForError ());
87                                         Report.Warning (3017, 1, a.Location, "You cannot specify the CLSCompliant attribute on a module that differs from the CLSCompliant attribute on the assembly");
88                                         return;
89                                 }
90                         }
91
92                         Builder.SetCustomAttribute (cb);
93                 }
94
95                 public override void Emit ()
96                 {
97                         if (OptAttributes != null)
98                                 OptAttributes.Emit ();
99
100                         if (is_unsafe) {
101                                 Type t = TypeManager.CoreLookupType ("System.Security", "UnverifiableCodeAttribute", Kind.Class, true);
102                                 if (t != null) {
103                                         ConstructorInfo unverifiable_code_ctor = TypeManager.GetPredefinedConstructor (t, Location.Null, Type.EmptyTypes);
104                                         if (unverifiable_code_ctor != null)
105                                                 Builder.SetCustomAttribute (new CustomAttributeBuilder (unverifiable_code_ctor, new object [0]));
106                                 }
107                         }
108                 }
109
110                 public AnonymousTypeClass GetAnonymousType (ArrayList parameters)
111                 {
112                         ArrayList candidates = (ArrayList) anonymous_types [parameters.Count];
113                         if (candidates == null)
114                                 return null;
115
116                         int i;
117                         foreach (AnonymousTypeClass at in candidates) {
118                                 for (i = 0; i < parameters.Count; ++i) {
119                                         if (!parameters [i].Equals (at.Parameters [i]))
120                                                 break;
121                                 }
122
123                                 if (i == parameters.Count)
124                                         return at;
125                         }
126
127                         return null;
128                 }
129
130                 public override bool GetClsCompliantAttributeValue ()
131                 {
132                         return CodeGen.Assembly.IsClsCompliant;
133                 }
134
135                 public bool HasDefaultCharSet {
136                         get {
137                                 return has_default_charset;
138                         }
139                 }
140
141                 public override string GetSignatureForError ()
142                 {
143                         return "<module>";
144                 }
145
146                 public override bool IsClsComplianceRequired ()
147                 {
148                         return true;
149                 }
150
151                 public override ModuleContainer Module {
152                         get {
153                                 return this;
154                         }
155                 }
156
157                 public override IResolveContext ResolveContext {
158                         get { return this; }
159                 }
160
161                 protected override bool AddMemberType (DeclSpace ds)
162                 {
163                         if (!AddToContainer (ds, ds.Name))
164                                 return false;
165                         ds.NamespaceEntry.NS.AddDeclSpace (ds.Basename, ds);
166                         return true;
167                 }
168
169                 protected override void RemoveMemberType (DeclSpace ds)
170                 {
171                         ds.NamespaceEntry.NS.RemoveDeclSpace (ds.Basename);
172                         base.RemoveMemberType (ds);
173                 }
174
175                 /// <summary>
176                 /// It is called very early therefore can resolve only predefined attributes
177                 /// </summary>
178                 public void Resolve ()
179                 {
180                         if (OptAttributes == null)
181                                 return;
182
183                         if (!OptAttributes.CheckTargets ())
184                                 return;
185
186                         Attribute a = ResolveAttribute (PredefinedAttributes.Get.DefaultCharset);
187                         if (a != null) {
188                                 has_default_charset = true;
189                                 DefaultCharSet = a.GetCharSetValue ();
190                                 switch (DefaultCharSet) {
191                                 case CharSet.Ansi:
192                                 case CharSet.None:
193                                         break;
194                                 case CharSet.Auto:
195                                         DefaultCharSetType = TypeAttributes.AutoClass;
196                                         break;
197                                 case CharSet.Unicode:
198                                         DefaultCharSetType = TypeAttributes.UnicodeClass;
199                                         break;
200                                 default:
201                                         Report.Error (1724, a.Location, "Value specified for the argument to 'System.Runtime.InteropServices.DefaultCharSetAttribute' is not valid");
202                                         break;
203                                 }
204                         }
205                 }
206
207                 Attribute ResolveAttribute (PredefinedAttribute a_type)
208                 {
209                         Attribute a = OptAttributes.Search (a_type);
210                         if (a != null) {
211                                 a.Resolve ();
212                         }
213                         return a;
214                 }
215
216                 public override string[] ValidAttributeTargets {
217                         get {
218                                 return attribute_targets;
219                         }
220                 }
221         }
222
223         class RootDeclSpace : DeclSpace {
224                 public RootDeclSpace (NamespaceEntry ns)
225                         : base (ns, null, MemberName.Null, null)
226                 {
227                         PartialContainer = RootContext.ToplevelTypes;
228                 }
229
230                 public override AttributeTargets AttributeTargets {
231                         get { throw new InternalErrorException ("should not be called"); }
232                 }
233
234                 public override string DocCommentHeader {
235                         get { throw new InternalErrorException ("should not be called"); }
236                 }
237
238                 public override bool Define ()
239                 {
240                         throw new InternalErrorException ("should not be called");
241                 }
242
243                 public override TypeBuilder DefineType ()
244                 {
245                         throw new InternalErrorException ("should not be called");
246                 }
247
248                 public override MemberCache MemberCache {
249                         get { return PartialContainer.MemberCache; }
250                 }
251
252                 public override ModuleContainer Module {
253                         get {
254                                 return PartialContainer.Module;
255                         }
256                 }
257
258                 public override bool GetClsCompliantAttributeValue ()
259                 {
260                         return PartialContainer.GetClsCompliantAttributeValue ();
261                 }
262
263                 public override bool IsClsComplianceRequired ()
264                 {
265                         return PartialContainer.IsClsComplianceRequired ();
266                 }
267         }
268 }