Few mcs property accessors tweaks
[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.Generic;
15 using System.Runtime.InteropServices;
16 using Mono.CompilerServices.SymbolWriter;
17
18 #if STATIC
19 using IKVM.Reflection;
20 using IKVM.Reflection.Emit;
21 #else
22 using System.Reflection;
23 using System.Reflection.Emit;
24 #endif
25
26 namespace Mono.CSharp
27 {
28         //
29         // Module (top-level type) container
30         //
31         public class ModuleContainer : TypeContainer
32         {
33 #if STATIC
34                 //
35                 // Compiler generated container for static data
36                 //
37                 sealed class StaticDataContainer : CompilerGeneratedClass
38                 {
39                         Dictionary<int, Struct> size_types;
40                         new int fields;
41
42                         public StaticDataContainer (ModuleContainer module)
43                                 : base (module, new MemberName ("<PrivateImplementationDetails>" + module.builder.ModuleVersionId.ToString ("B"), Location.Null), Modifiers.STATIC)
44                         {
45                                 size_types = new Dictionary<int, Struct> ();
46                         }
47
48                         public override void CloseType ()
49                         {
50                                 base.CloseType ();
51
52                                 foreach (var entry in size_types) {
53                                         entry.Value.CloseType ();
54                                 }
55                         }
56
57                         public FieldSpec DefineInitializedData (byte[] data, Location loc)
58                         {
59                                 Struct size_type;
60                                 if (!size_types.TryGetValue (data.Length, out size_type)) {
61                                         //
62                                         // Build common type for this data length. We cannot use
63                                         // DefineInitializedData because it creates public type,
64                                         // and its name is not unique among modules
65                                         //
66                                         size_type = new Struct (null, this, new MemberName ("$ArrayType=" + data.Length, Location), Modifiers.PRIVATE | Modifiers.COMPILER_GENERATED, null);
67                                         size_type.CreateType ();
68                                         size_type.DefineType ();
69
70                                         size_types.Add (data.Length, size_type);
71
72                                         var pa = Module.PredefinedAttributes.StructLayout;
73                                         if (pa.Constructor != null || pa.ResolveConstructor (Location, TypeManager.short_type)) {
74                                                 var argsEncoded = new AttributeEncoder ();
75                                                 argsEncoded.Encode ((short) LayoutKind.Explicit);
76
77                                                 var field_size = pa.GetField ("Size", TypeManager.int32_type, Location);
78                                                 var pack = pa.GetField ("Pack", TypeManager.int32_type, Location);
79                                                 if (field_size != null) {
80                                                         argsEncoded.EncodeNamedArguments (
81                                                                 new[] { field_size, pack },
82                                                                 new[] { new IntConstant ((int) data.Length, Location), new IntConstant (1, Location) }
83                                                         );
84                                                 }
85
86                                                 pa.EmitAttribute (size_type.TypeBuilder, argsEncoded);
87                                         }
88                                 }
89
90                                 var name = "$field-" + fields.ToString ("X");
91                                 ++fields;
92                                 const Modifiers fmod = Modifiers.STATIC | Modifiers.INTERNAL;
93                                 var fbuilder = TypeBuilder.DefineField (name, size_type.CurrentType.GetMetaInfo (), ModifiersExtensions.FieldAttr (fmod) | FieldAttributes.HasFieldRVA);
94                                 fbuilder.__SetDataAndRVA (data);
95
96                                 return new FieldSpec (CurrentType, null, size_type.CurrentType, fbuilder, fmod);
97                         }
98                 }
99
100                 StaticDataContainer static_data;
101
102                 //
103                 // Makes const data field inside internal type container
104                 //
105                 public FieldSpec MakeStaticData (byte[] data, Location loc)
106                 {
107                         if (static_data == null) {
108                                 static_data = new StaticDataContainer (this);
109                                 static_data.CreateType ();
110                                 static_data.DefineType ();
111
112                                 AddCompilerGeneratedClass (static_data);
113                         }
114
115                         return static_data.DefineInitializedData (data, loc);
116                 }
117 #endif
118
119                 public CharSet? DefaultCharSet;
120                 public TypeAttributes DefaultCharSetType = TypeAttributes.AnsiClass;
121
122                 Dictionary<int, List<AnonymousTypeClass>> anonymous_types;
123
124                 AssemblyDefinition assembly;
125                 readonly CompilerContext context;
126                 readonly RootNamespace global_ns;
127                 Dictionary<string, RootNamespace> alias_ns;
128
129                 ModuleBuilder builder;
130
131                 bool has_extenstion_method;
132
133                 PredefinedAttributes predefined_attributes;
134                 PredefinedTypes predefined_types;
135
136                 static readonly string[] attribute_targets = new string[] { "assembly", "module" };
137
138                 public ModuleContainer (CompilerContext context)
139                         : base (null, null, MemberName.Null, null, 0)
140                 {
141                         this.context = context;
142
143                         caching_flags &= ~(Flags.Obsolete_Undetected | Flags.Excluded_Undetected);
144
145                         types = new List<TypeContainer> ();
146                         anonymous_types = new Dictionary<int, List<AnonymousTypeClass>> ();
147                         global_ns = new GlobalRootNamespace ();
148                         alias_ns = new Dictionary<string, RootNamespace> ();
149                 }
150
151                 #region Properties
152
153                 public override AttributeTargets AttributeTargets {
154                         get {
155                                 return AttributeTargets.Assembly;
156                         }
157                 }
158
159                 public ModuleBuilder Builder {
160                         get {
161                                 return builder;
162                         }
163                 }
164
165                 public override CompilerContext Compiler {
166                         get {
167                                 return context;
168                         }
169                 }
170
171                 public override AssemblyDefinition DeclaringAssembly {
172                         get {
173                                 return assembly;
174                         }
175                 }
176
177                 public bool HasDefaultCharSet {
178                         get {
179                                 return DefaultCharSet.HasValue;
180                         }
181                 }
182
183                 public bool HasExtensionMethod {
184                         get {
185                                 return has_extenstion_method;
186                         }
187                         set {
188                                 has_extenstion_method = value;
189                         }
190                 }
191
192                 //
193                 // Returns module global:: namespace
194                 //
195                 public RootNamespace GlobalRootNamespace {
196                     get {
197                         return global_ns;
198                     }
199                 }
200
201                 public override ModuleContainer Module {
202                         get {
203                                 return this;
204                         }
205                 }
206
207                 internal PredefinedAttributes PredefinedAttributes {
208                         get {
209                                 return predefined_attributes;
210                         }
211                 }
212
213                 internal PredefinedTypes PredefinedTypes {
214                         get {
215                                 return predefined_types;
216                         }
217                 }
218
219                 public override string[] ValidAttributeTargets {
220                         get {
221                                 return attribute_targets;
222                         }
223                 }
224
225                 #endregion
226
227                 public void AddAnonymousType (AnonymousTypeClass type)
228                 {
229                         List<AnonymousTypeClass> existing;
230                         if (!anonymous_types.TryGetValue (type.Parameters.Count, out existing))
231                         if (existing == null) {
232                                 existing = new List<AnonymousTypeClass> ();
233                                 anonymous_types.Add (type.Parameters.Count, existing);
234                         }
235
236                         existing.Add (type);
237                 }
238
239                 public void AddAttributes (List<Attribute> attrs)
240                 {
241                         AddAttributes (attrs, this);
242                 }
243
244                 public void AddAttributes (List<Attribute> attrs, IMemberContext context)
245                 {
246                         foreach (Attribute a in attrs)
247                                 a.AttachTo (this, context);
248
249                         if (attributes == null) {
250                                 attributes = new Attributes (attrs);
251                                 return;
252                         }
253                         attributes.AddAttributes (attrs);
254                 }
255
256                 public override TypeContainer AddPartial (TypeContainer nextPart)
257                 {
258                         return AddPartial (nextPart, nextPart.Name);
259                 }
260
261                 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
262                 {
263                         if (a.Target == AttributeTargets.Assembly) {
264                                 assembly.ApplyAttributeBuilder (a, ctor, cdata, pa);
265                                 return;
266                         }
267
268                         if (a.Type == pa.DefaultCharset) {
269                                 switch (a.GetCharSetValue ()) {
270                                 case CharSet.Ansi:
271                                 case CharSet.None:
272                                         break;
273                                 case CharSet.Auto:
274                                         DefaultCharSet = CharSet.Auto;
275                                         DefaultCharSetType = TypeAttributes.AutoClass;
276                                         break;
277                                 case CharSet.Unicode:
278                                         DefaultCharSet = CharSet.Unicode;
279                                         DefaultCharSetType = TypeAttributes.UnicodeClass;
280                                         break;
281                                 default:
282                                         Report.Error (1724, a.Location, "Value specified for the argument to `{0}' is not valid",
283                                                 a.GetSignatureForError ());
284                                         break;
285                                 }
286                         } else if (a.Type == pa.CLSCompliant) {
287                                 Attribute cls = DeclaringAssembly.CLSCompliantAttribute;
288                                 if (cls == null) {
289                                         Report.Warning (3012, 1, a.Location,
290                                                 "You must specify the CLSCompliant attribute on the assembly, not the module, to enable CLS compliance checking");
291                                 } else if (DeclaringAssembly.IsCLSCompliant != a.GetBoolean ()) {
292                                         Report.SymbolRelatedToPreviousError (cls.Location, cls.GetSignatureForError ());
293                                         Report.Warning (3017, 1, a.Location,
294                                                 "You cannot specify the CLSCompliant attribute on a module that differs from the CLSCompliant attribute on the assembly");
295                                         return;
296                                 }
297                         }
298
299                         builder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), cdata);
300                 }
301
302                 public override void CloseType ()
303                 {
304                         foreach (TypeContainer tc in types) {
305                                 tc.CloseType ();
306                         }
307
308                         if (compiler_generated != null)
309                                 foreach (CompilerGeneratedClass c in compiler_generated)
310                                         c.CloseType ();
311                 }
312
313                 public TypeBuilder CreateBuilder (string name, TypeAttributes attr, int typeSize)
314                 {
315                         return builder.DefineType (name, attr, null, typeSize);
316                 }
317
318                 //
319                 // Creates alias global namespace
320                 //
321                 public RootNamespace CreateRootNamespace (string alias)
322                 {
323                         if (alias == global_ns.Alias) {
324                                 NamespaceEntry.Error_GlobalNamespaceRedefined (Location.Null, Report);
325                                 return global_ns;
326                         }
327
328                         RootNamespace rn;
329                         if (!alias_ns.TryGetValue (alias, out rn)) {
330                                 rn = new RootNamespace (alias);
331                                 alias_ns.Add (alias, rn);
332                         }
333
334                         return rn;
335                 }
336
337                 public void Create (AssemblyDefinition assembly, ModuleBuilder moduleBuilder)
338                 {
339                         this.assembly = assembly;
340                         builder = moduleBuilder;
341                 }
342
343                 public new void CreateType ()
344                 {
345                         foreach (TypeContainer tc in types)
346                                 tc.CreateType ();
347                 }
348
349                 public new void Define ()
350                 {
351                         InitializePredefinedTypes ();
352
353                         foreach (TypeContainer tc in types)
354                                 tc.DefineType ();
355
356                         foreach (TypeContainer tc in types)
357                                 tc.ResolveTypeParameters ();
358
359                         foreach (TypeContainer tc in types) {
360                                 try {
361                                         tc.Define ();
362                                 } catch (Exception e) {
363                                         throw new InternalErrorException (tc, e);
364                                 }
365                         }
366                 }
367
368                 public override void Emit ()
369                 {
370                         if (OptAttributes != null)
371                                 OptAttributes.Emit ();
372
373                         if (RootContext.Unsafe) {
374                                 var pa = PredefinedAttributes.UnverifiableCode;
375                                 if (pa.IsDefined)
376                                         pa.EmitAttribute (builder);
377                         }
378
379                         foreach (var tc in types)
380                                 tc.DefineConstants ();
381
382                         foreach (TypeContainer tc in types)
383                                 tc.EmitType ();
384
385                         if (Compiler.Report.Errors > 0)
386                                 return;
387
388                         foreach (TypeContainer tc in types)
389                                 tc.VerifyMembers ();
390
391                         if (compiler_generated != null)
392                                 foreach (var c in compiler_generated)
393                                         c.EmitType ();
394                 }
395
396                 public AnonymousTypeClass GetAnonymousType (IList<AnonymousTypeParameter> parameters)
397                 {
398                         List<AnonymousTypeClass> candidates;
399                         if (!anonymous_types.TryGetValue (parameters.Count, out candidates))
400                                 return null;
401
402                         int i;
403                         foreach (AnonymousTypeClass at in candidates) {
404                                 for (i = 0; i < parameters.Count; ++i) {
405                                         if (!parameters [i].Equals (at.Parameters [i]))
406                                                 break;
407                                 }
408
409                                 if (i == parameters.Count)
410                                         return at;
411                         }
412
413                         return null;
414                 }
415
416                 public RootNamespace GetRootNamespace (string name)
417                 {
418                         RootNamespace rn;
419                         alias_ns.TryGetValue (name, out rn);
420                         return rn;
421                 }
422
423                 public override string GetSignatureForError ()
424                 {
425                         return "<module>";
426                 }
427
428                 public void InitializePredefinedTypes ()
429                 {
430                         predefined_attributes = new PredefinedAttributes (this);
431                         predefined_types = new PredefinedTypes (this);
432                 }
433
434                 public override bool IsClsComplianceRequired ()
435                 {
436                         return DeclaringAssembly.IsCLSCompliant;
437                 }
438
439                 protected override bool AddMemberType (TypeContainer ds)
440                 {
441                         if (!AddToContainer (ds, ds.Name))
442                                 return false;
443                         ds.NamespaceEntry.NS.AddType (ds.Definition);
444                         return true;
445                 }
446
447                 protected override void RemoveMemberType (DeclSpace ds)
448                 {
449                         ds.NamespaceEntry.NS.RemoveDeclSpace (ds.Basename);
450                         base.RemoveMemberType (ds);
451                 }
452
453                 public Attribute ResolveAssemblyAttribute (PredefinedAttribute a_type)
454                 {
455                         Attribute a = OptAttributes.Search ("assembly", a_type);
456                         if (a != null) {
457                                 a.Resolve ();
458                         }
459                         return a;
460                 }
461
462                 public void SetDeclaringAssembly (AssemblyDefinition assembly)
463                 {
464                         // TODO: This setter is quite ugly but I have not found a way around it yet
465                         this.assembly = assembly;
466                 }
467         }
468
469         class RootDeclSpace : TypeContainer {
470                 public RootDeclSpace (NamespaceEntry ns)
471                         : base (ns, null, MemberName.Null, null, 0)
472                 {
473                         PartialContainer = RootContext.ToplevelTypes;
474                 }
475
476                 public override AttributeTargets AttributeTargets {
477                         get { throw new InternalErrorException ("should not be called"); }
478                 }
479
480                 public override CompilerContext Compiler {
481                         get {
482                                 return PartialContainer.Compiler;
483                         }
484                 }
485
486                 public override string DocCommentHeader {
487                         get { throw new InternalErrorException ("should not be called"); }
488                 }
489
490                 public override void DefineType ()
491                 {
492                         throw new InternalErrorException ("should not be called");
493                 }
494
495                 public override ModuleContainer Module {
496                         get {
497                                 return PartialContainer.Module;
498                         }
499                 }
500
501                 public override bool IsClsComplianceRequired ()
502                 {
503                         return PartialContainer.IsClsComplianceRequired ();
504                 }
505
506                 public override FullNamedExpression LookupNamespaceAlias (string name)
507                 {
508                         return NamespaceEntry.LookupNamespaceAlias (name);
509                 }
510         }
511 }