Free cookie consent management tool by TermsFeed Policy Generator

source: branches/CodeEditor/HeuristicLab.ExtLibs/HeuristicLab.NRefactory/5.5.0/NRefactory.CSharp-5.5.0/Parser/mcs/module.cs @ 11700

Last change on this file since 11700 was 11700, checked in by jkarder, 9 years ago

#2077: created branch and added first version

File size: 19.1 KB
Line 
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
14using System;
15using System.Collections.Generic;
16using System.Runtime.InteropServices;
17using Mono.CompilerServices.SymbolWriter;
18using System.Linq;
19
20#if STATIC
21using IKVM.Reflection;
22using IKVM.Reflection.Emit;
23#else
24using System.Reflection;
25using System.Reflection.Emit;
26#endif
27
28namespace 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 sealed class PatternMatchingHelper : CompilerGeneratedContainer
109    {
110      public PatternMatchingHelper (ModuleContainer module)
111        : base (module, new MemberName ("<PatternMatchingHelper>", Location.Null),
112          Modifiers.STATIC | Modifiers.INTERNAL | Modifiers.DEBUGGER_HIDDEN)
113      {
114      }
115
116      public Method NumberMatcher { get; private set; }
117
118      protected override bool DoDefineMembers ()
119      {
120        if (!base.DoDefineMembers ())
121          return false;
122
123        NumberMatcher = GenerateNumberMatcher ();
124        return true;
125      }
126
127      Method GenerateNumberMatcher ()
128      {
129        var loc = Location;
130        var parameters = ParametersCompiled.CreateFullyResolved (
131          new [] {
132            new Parameter (new TypeExpression (Compiler.BuiltinTypes.Object, loc), "obj", 0, null, loc),
133            new Parameter (new TypeExpression (Compiler.BuiltinTypes.Object, loc), "value", 0, null, loc),
134            new Parameter (new TypeExpression (Compiler.BuiltinTypes.Bool, loc), "enumType", 0, null, loc),
135          },
136          new [] {
137            Compiler.BuiltinTypes.Object,
138            Compiler.BuiltinTypes.Object,
139            Compiler.BuiltinTypes.Bool
140          });
141
142        var m = new Method (this, new TypeExpression (Compiler.BuiltinTypes.Bool, loc),
143          Modifiers.PUBLIC | Modifiers.STATIC | Modifiers.DEBUGGER_HIDDEN, new MemberName ("NumberMatcher", loc),
144          parameters, null);
145
146        parameters [0].Resolve (m, 0);
147        parameters [1].Resolve (m, 1);
148        parameters [2].Resolve (m, 2);
149
150        ToplevelBlock top_block = new ToplevelBlock (Compiler, parameters, loc);
151        m.Block = top_block;
152
153        //
154        // if (enumType)
155        //    return Equals (obj, value);
156        //
157        var equals_args = new Arguments (2);
158        equals_args.Add (new Argument (top_block.GetParameterReference (0, loc)));
159        equals_args.Add (new Argument (top_block.GetParameterReference (1, loc)));
160
161        var if_type = new If (
162                        top_block.GetParameterReference (2, loc),
163                        new Return (new Invocation (new SimpleName ("Equals", loc), equals_args), loc),
164                        loc);
165
166        top_block.AddStatement (if_type);
167
168        //
169        // if (obj is Enum || obj == null)
170        //    return false;
171        //
172
173        var if_enum = new If (
174                        new Binary (Binary.Operator.LogicalOr,
175                          new Is (top_block.GetParameterReference (0, loc), new TypeExpression (Compiler.BuiltinTypes.Enum, loc), loc),
176                          new Binary (Binary.Operator.Equality, top_block.GetParameterReference (0, loc), new NullLiteral (loc))),
177                        new Return (new BoolLiteral (Compiler.BuiltinTypes, false, loc), loc),
178                        loc);
179
180        top_block.AddStatement (if_enum);
181
182
183        var system_convert = new MemberAccess (new QualifiedAliasMember ("global", "System", loc), "Convert", loc);
184
185        //
186        // var converted = System.Convert.ChangeType (obj, System.Convert.GetTypeCode (value));
187        //
188        var lv_converted = LocalVariable.CreateCompilerGenerated (Compiler.BuiltinTypes.Object, top_block, loc);
189
190        var arguments_gettypecode = new Arguments (1);
191        arguments_gettypecode.Add (new Argument (top_block.GetParameterReference (1, loc)));
192
193        var gettypecode = new Invocation (new MemberAccess (system_convert, "GetTypeCode", loc), arguments_gettypecode);
194
195        var arguments_changetype = new Arguments (1);
196        arguments_changetype.Add (new Argument (top_block.GetParameterReference (0, loc)));
197        arguments_changetype.Add (new Argument (gettypecode));
198
199        var changetype = new Invocation (new MemberAccess (system_convert, "ChangeType", loc), arguments_changetype);
200
201        top_block.AddStatement (new StatementExpression (new SimpleAssign (new LocalVariableReference (lv_converted, loc), changetype, loc)));
202
203
204        //
205        // return converted.Equals (value)
206        //
207        var equals_arguments = new Arguments (1);
208        equals_arguments.Add (new Argument (top_block.GetParameterReference (1, loc)));
209        var equals_invocation = new Invocation (new MemberAccess (new LocalVariableReference (lv_converted, loc), "Equals"), equals_arguments);
210        top_block.AddStatement (new Return (equals_invocation, loc));
211
212        m.Define ();
213        m.PrepareEmit ();
214        AddMember (m);
215
216        return m;
217      }
218    }
219
220    PatternMatchingHelper pmh;
221
222    public PatternMatchingHelper CreatePatterMatchingHelper ()
223    {
224      if (pmh == null) {
225        pmh = new PatternMatchingHelper (this);
226
227        pmh.CreateContainer ();
228        pmh.DefineContainer ();
229        pmh.Define ();
230        AddCompilerGeneratedClass (pmh);
231      }
232
233      return pmh;
234    }
235
236    public CharSet? DefaultCharSet;
237    public TypeAttributes DefaultCharSetType = TypeAttributes.AnsiClass;
238
239    readonly Dictionary<int, List<AnonymousTypeClass>> anonymous_types;
240    readonly Dictionary<ArrayContainer.TypeRankPair, ArrayContainer> array_types;
241    readonly Dictionary<TypeSpec, PointerContainer> pointer_types;
242    readonly Dictionary<TypeSpec, ReferenceContainer> reference_types;
243    readonly Dictionary<TypeSpec, MethodSpec> attrs_cache;
244    readonly Dictionary<TypeSpec, AwaiterDefinition> awaiters;
245
246    AssemblyDefinition assembly;
247    readonly CompilerContext context;
248    readonly RootNamespace global_ns;
249    readonly Dictionary<string, RootNamespace> alias_ns;
250
251    ModuleBuilder builder;
252
253    bool has_extenstion_method;
254
255    PredefinedAttributes predefined_attributes;
256    PredefinedTypes predefined_types;
257    PredefinedMembers predefined_members;
258
259    public Binary.PredefinedOperator[] OperatorsBinaryEqualityLifted;
260    public Binary.PredefinedOperator[] OperatorsBinaryLifted;
261
262    static readonly string[] attribute_targets = new string[] { "assembly", "module" };
263
264    public ModuleContainer (CompilerContext context)
265      : base (null, MemberName.Null, null, 0)
266    {
267      this.context = context;
268
269      caching_flags &= ~(Flags.Obsolete_Undetected | Flags.Excluded_Undetected);
270
271      containers = new List<TypeContainer> ();
272      anonymous_types = new Dictionary<int, List<AnonymousTypeClass>> ();
273      global_ns = new GlobalRootNamespace ();
274      alias_ns = new Dictionary<string, RootNamespace> ();
275      array_types = new Dictionary<ArrayContainer.TypeRankPair, ArrayContainer> ();
276      pointer_types = new Dictionary<TypeSpec, PointerContainer> ();
277      reference_types = new Dictionary<TypeSpec, ReferenceContainer> ();
278      attrs_cache = new Dictionary<TypeSpec, MethodSpec> ();
279      awaiters = new Dictionary<TypeSpec, AwaiterDefinition> ();
280    }
281
282    #region Properties
283
284    internal Dictionary<ArrayContainer.TypeRankPair, ArrayContainer> ArrayTypesCache {
285      get {
286        return array_types;
287      }
288    }
289
290    //
291    // Cache for parameter-less attributes
292    //
293    internal Dictionary<TypeSpec, MethodSpec> AttributeConstructorCache {
294      get {
295        return attrs_cache;
296      }
297    }
298
299    public override AttributeTargets AttributeTargets {
300      get {
301        return AttributeTargets.Assembly;
302      }
303    }
304
305    public ModuleBuilder Builder {
306      get {
307        return builder;
308      }
309    }
310
311    public override CompilerContext Compiler {
312      get {
313        return context;
314      }
315    }
316
317    public int CounterAnonymousTypes { get; set; }
318
319    public AssemblyDefinition DeclaringAssembly {
320      get {
321        return assembly;
322      }
323    }
324
325    internal DocumentationBuilder DocumentationBuilder {
326      get; set;
327    }
328
329    public override string DocCommentHeader {
330      get {
331        throw new NotSupportedException ();
332      }
333    }
334
335    public Evaluator Evaluator {
336      get; set;
337    }
338
339    public bool HasDefaultCharSet {
340      get {
341        return DefaultCharSet.HasValue;
342      }
343    }
344
345    public bool HasExtensionMethod {
346      get {
347        return has_extenstion_method;
348      }
349      set {
350        has_extenstion_method = value;
351      }
352    }
353
354    public bool HasTypesFullyDefined {
355      get; set;
356    }
357
358    //
359    // Returns module global:: namespace
360    //
361    public RootNamespace GlobalRootNamespace {
362        get {
363            return global_ns;
364        }
365    }
366
367    public override ModuleContainer Module {
368      get {
369        return this;
370      }
371    }
372
373    internal Dictionary<TypeSpec, PointerContainer> PointerTypesCache {
374      get {
375        return pointer_types;
376      }
377    }
378
379    internal PredefinedAttributes PredefinedAttributes {
380      get {
381        return predefined_attributes;
382      }
383    }
384
385    internal PredefinedMembers PredefinedMembers {
386      get {
387        return predefined_members;
388      }
389    }
390
391    internal PredefinedTypes PredefinedTypes {
392      get {
393        return predefined_types;
394      }
395    }
396
397    internal Dictionary<TypeSpec, ReferenceContainer> ReferenceTypesCache {
398      get {
399        return reference_types;
400      }
401    }
402
403    public override string[] ValidAttributeTargets {
404      get {
405        return attribute_targets;
406      }
407    }
408
409    #endregion
410
411    public override void Accept (StructuralVisitor visitor)
412    {
413      visitor.Visit (this);
414    }
415
416    public void AddAnonymousType (AnonymousTypeClass type)
417    {
418      List<AnonymousTypeClass> existing;
419      if (!anonymous_types.TryGetValue (type.Parameters.Count, out existing))
420      if (existing == null) {
421        existing = new List<AnonymousTypeClass> ();
422        anonymous_types.Add (type.Parameters.Count, existing);
423      }
424
425      existing.Add (type);
426    }
427
428    public void AddAttribute (Attribute attr, IMemberContext context)
429    {
430      attr.AttachTo (this, context);
431
432      if (attributes == null) {
433        attributes = new Attributes (attr);
434        return;
435      }
436
437      attributes.AddAttribute (attr);
438    }
439
440    public override void AddTypeContainer (TypeContainer tc)
441    {
442      AddTypeContainerMember (tc);
443    }
444
445    public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
446    {
447      if (a.Target == AttributeTargets.Assembly) {
448        assembly.ApplyAttributeBuilder (a, ctor, cdata, pa);
449        return;
450      }
451
452      if (a.Type == pa.DefaultCharset) {
453        switch (a.GetCharSetValue ()) {
454        case CharSet.Ansi:
455        case CharSet.None:
456          break;
457        case CharSet.Auto:
458          DefaultCharSet = CharSet.Auto;
459          DefaultCharSetType = TypeAttributes.AutoClass;
460          break;
461        case CharSet.Unicode:
462          DefaultCharSet = CharSet.Unicode;
463          DefaultCharSetType = TypeAttributes.UnicodeClass;
464          break;
465        default:
466          Report.Error (1724, a.Location, "Value specified for the argument to `{0}' is not valid",
467            a.GetSignatureForError ());
468          break;
469        }
470      } else if (a.Type == pa.CLSCompliant) {
471        Attribute cls = DeclaringAssembly.CLSCompliantAttribute;
472        if (cls == null) {
473          Report.Warning (3012, 1, a.Location,
474            "You must specify the CLSCompliant attribute on the assembly, not the module, to enable CLS compliance checking");
475        } else if (DeclaringAssembly.IsCLSCompliant != a.GetBoolean ()) {
476          Report.SymbolRelatedToPreviousError (cls.Location, cls.GetSignatureForError ());
477          Report.Warning (3017, 1, a.Location,
478            "You cannot specify the CLSCompliant attribute on a module that differs from the CLSCompliant attribute on the assembly");
479          return;
480        }
481      }
482
483      builder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), cdata);
484    }
485
486    public override void CloseContainer ()
487    {
488      if (anonymous_types != null) {
489        foreach (var atypes in anonymous_types)
490          foreach (var at in atypes.Value)
491            at.CloseContainer ();
492      }
493
494      base.CloseContainer ();
495    }
496
497    public TypeBuilder CreateBuilder (string name, TypeAttributes attr, int typeSize)
498    {
499      return builder.DefineType (name, attr, null, typeSize);
500    }
501
502    //
503    // Creates alias global namespace
504    //
505    public RootNamespace CreateRootNamespace (string alias)
506    {
507      if (alias == global_ns.Alias) {
508        RootNamespace.Error_GlobalNamespaceRedefined (Report, Location.Null);
509        return global_ns;
510      }
511
512      RootNamespace rn;
513      if (!alias_ns.TryGetValue (alias, out rn)) {
514        rn = new RootNamespace (alias);
515        alias_ns.Add (alias, rn);
516      }
517
518      return rn;
519    }
520
521    public void Create (AssemblyDefinition assembly, ModuleBuilder moduleBuilder)
522    {
523      this.assembly = assembly;
524      builder = moduleBuilder;
525    }
526
527    public override bool Define ()
528    {
529      DefineContainer ();
530
531      ExpandBaseInterfaces ();
532
533      base.Define ();
534
535      HasTypesFullyDefined = true;
536
537      return true;
538    }
539
540    public override bool DefineContainer ()
541    {
542      DefineNamespace ();
543
544      return base.DefineContainer ();
545    }
546
547    public void EnableRedefinition ()
548    {
549      is_defined = false;
550    }
551
552    public override void EmitContainer ()
553    {
554      if (OptAttributes != null)
555        OptAttributes.Emit ();
556
557      if (Compiler.Settings.Unsafe && !assembly.IsSatelliteAssembly) {
558        var pa = PredefinedAttributes.UnverifiableCode;
559        if (pa.IsDefined)
560          pa.EmitAttribute (builder);
561      }
562
563      foreach (var tc in containers) {
564        tc.PrepareEmit ();
565      }
566
567      base.EmitContainer ();
568
569      if (Compiler.Report.Errors == 0 && !Compiler.Settings.WriteMetadataOnly)
570        VerifyMembers ();
571
572      if (anonymous_types != null) {
573        foreach (var atypes in anonymous_types)
574          foreach (var at in atypes.Value)
575            at.EmitContainer ();
576      }
577    }
578
579    internal override void GenerateDocComment (DocumentationBuilder builder)
580    {
581      foreach (var tc in containers)
582        tc.GenerateDocComment (builder);
583    }
584
585    public AnonymousTypeClass GetAnonymousType (IList<AnonymousTypeParameter> parameters)
586    {
587      List<AnonymousTypeClass> candidates;
588      if (!anonymous_types.TryGetValue (parameters.Count, out candidates))
589        return null;
590
591      int i;
592      foreach (AnonymousTypeClass at in candidates) {
593        for (i = 0; i < parameters.Count; ++i) {
594          if (!parameters [i].Equals (at.Parameters [i]))
595            break;
596        }
597
598        if (i == parameters.Count)
599          return at;
600      }
601
602      return null;
603    }
604
605    //
606    // Return container with awaiter definition. It never returns null
607    // but all container member can be null for easier error reporting
608    //
609    public AwaiterDefinition GetAwaiter (TypeSpec type)
610    {
611      AwaiterDefinition awaiter;
612      if (awaiters.TryGetValue (type, out awaiter))
613        return awaiter;
614
615      awaiter = new AwaiterDefinition ();
616
617      //
618      // Predefined: bool IsCompleted { get; }
619      //
620      awaiter.IsCompleted = MemberCache.FindMember (type, MemberFilter.Property ("IsCompleted", Compiler.BuiltinTypes.Bool),
621        BindingRestriction.InstanceOnly) as PropertySpec;
622
623      //
624      // Predefined: GetResult ()
625      //
626      // The method return type is also result type of await expression
627      //
628      awaiter.GetResult = MemberCache.FindMember (type, MemberFilter.Method ("GetResult", 0,
629        ParametersCompiled.EmptyReadOnlyParameters, null),
630        BindingRestriction.InstanceOnly) as MethodSpec;
631
632      //
633      // Predefined: INotifyCompletion.OnCompleted (System.Action)
634      //
635      var nc = PredefinedTypes.INotifyCompletion;
636      awaiter.INotifyCompletion = !nc.Define () || type.ImplementsInterface (nc.TypeSpec, false);
637
638      awaiters.Add (type, awaiter);
639      return awaiter;
640    }
641
642    public override void GetCompletionStartingWith (string prefix, List<string> results)
643    {
644      var names = Evaluator.GetVarNames ();
645      results.AddRange (names.Where (l => l.StartsWith (prefix)));
646    }
647
648    public RootNamespace GetRootNamespace (string name)
649    {
650      RootNamespace rn;
651      alias_ns.TryGetValue (name, out rn);
652      return rn;
653    }
654
655    public override string GetSignatureForError ()
656    {
657      return "<module>";
658    }
659
660    public Binary.PredefinedOperator[] GetPredefinedEnumAritmeticOperators (TypeSpec enumType, bool nullable)
661    {
662      TypeSpec underlying;
663      Binary.Operator mask = 0;
664
665      if (nullable) {
666        underlying = Nullable.NullableInfo.GetEnumUnderlyingType (this, enumType);
667        mask = Binary.Operator.NullableMask;
668      } else {
669        underlying = EnumSpec.GetUnderlyingType (enumType);
670      }
671
672      var operators = new[] {
673        new Binary.PredefinedOperator (enumType, underlying,
674          mask | Binary.Operator.AdditionMask | Binary.Operator.SubtractionMask | Binary.Operator.DecomposedMask, enumType),
675        new Binary.PredefinedOperator (underlying, enumType,
676          mask | Binary.Operator.AdditionMask | Binary.Operator.SubtractionMask | Binary.Operator.DecomposedMask, enumType),
677        new Binary.PredefinedOperator (enumType, mask | Binary.Operator.SubtractionMask, underlying)
678      };
679
680      return operators;
681    }
682
683    public void InitializePredefinedTypes ()
684    {
685      predefined_attributes = new PredefinedAttributes (this);
686      predefined_types = new PredefinedTypes (this);
687      predefined_members = new PredefinedMembers (this);
688
689      OperatorsBinaryEqualityLifted = Binary.CreateEqualityLiftedOperatorsTable (this);
690      OperatorsBinaryLifted = Binary.CreateStandardLiftedOperatorsTable (this);
691    }
692
693    public override bool IsClsComplianceRequired ()
694    {
695      return DeclaringAssembly.IsCLSCompliant;
696    }
697
698    public Attribute ResolveAssemblyAttribute (PredefinedAttribute a_type)
699    {
700      Attribute a = OptAttributes.Search ("assembly", a_type);
701      if (a != null) {
702        a.Resolve ();
703      }
704      return a;
705    }
706
707    public void SetDeclaringAssembly (AssemblyDefinition assembly)
708    {
709      // TODO: This setter is quite ugly but I have not found a way around it yet
710      this.assembly = assembly;
711    }
712  }
713}
Note: See TracBrowser for help on using the repository browser.