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