Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/HeuristicLab.ExtLibs/HeuristicLab.NRefactory/5.5.0/NRefactory.CSharp-5.5.0/Parser/mcs/decl.cs @ 15888

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

#2077: created branch and added first version

File size: 33.3 KB
Line 
1//
2// decl.cs: Declaration base class for structs, classes, enums and interfaces.
3//
4// Author: Miguel de Icaza (miguel@gnu.org)
5//         Marek Safar (marek.safar@seznam.cz)
6//
7// Dual licensed under the terms of the MIT X11 or GNU GPL
8//
9// Copyright 2001 Ximian, Inc (http://www.ximian.com)
10// Copyright 2004-2008 Novell, Inc
11// Copyright 2011 Xamarin Inc
12//
13//
14
15using System;
16using System.Collections.Generic;
17using System.Diagnostics;
18using System.Text;
19using Mono.CompilerServices.SymbolWriter;
20
21#if NET_2_1
22using XmlElement = System.Object;
23#else
24using System.Xml;
25#endif
26
27#if STATIC
28using IKVM.Reflection;
29using IKVM.Reflection.Emit;
30#else
31using System.Reflection;
32using System.Reflection.Emit;
33#endif
34
35namespace Mono.CSharp {
36
37  //
38  // Better name would be DottenName
39  //
40  [DebuggerDisplay ("{GetSignatureForError()}")]
41  public class MemberName
42  {
43    public static readonly MemberName Null = new MemberName ("");
44
45    public readonly string Name;
46    public TypeParameters TypeParameters;
47    public readonly FullNamedExpression ExplicitInterface;
48    public readonly Location Location;
49
50    public readonly MemberName Left;
51
52    public MemberName (string name)
53      : this (name, Location.Null)
54    { }
55
56    public MemberName (string name, Location loc)
57      : this (null, name, loc)
58    { }
59
60    public MemberName (string name, TypeParameters tparams, Location loc)
61    {
62      this.Name = name;
63      this.Location = loc;
64
65      this.TypeParameters = tparams;
66    }
67
68    public MemberName (string name, TypeParameters tparams, FullNamedExpression explicitInterface, Location loc)
69      : this (name, tparams, loc)
70    {
71      this.ExplicitInterface = explicitInterface;
72    }
73
74    public MemberName (MemberName left, string name, Location loc)
75    {
76      this.Name = name;
77      this.Location = loc;
78      this.Left = left;
79    }
80
81    public MemberName (MemberName left, string name, FullNamedExpression explicitInterface, Location loc)
82      : this (left, name, loc)
83    {
84      this.ExplicitInterface = explicitInterface;
85    }
86
87    public MemberName (MemberName left, MemberName right)
88    {
89      this.Name = right.Name;
90      this.Location = right.Location;
91      this.TypeParameters = right.TypeParameters;
92      this.Left = left;
93    }
94
95    public int Arity {
96      get {
97        return TypeParameters == null ? 0 : TypeParameters.Count;
98      }
99    }
100
101    public bool IsGeneric {
102      get {
103        return TypeParameters != null;
104      }
105    }
106
107    public string Basename {
108      get {
109        if (TypeParameters != null)
110          return MakeName (Name, TypeParameters);
111        return Name;
112      }
113    }
114
115    public void CreateMetadataName (StringBuilder sb)
116    {
117      if (Left != null)
118        Left.CreateMetadataName (sb);
119
120      if (sb.Length != 0) {
121        sb.Append (".");
122      }
123
124      sb.Append (Basename);
125    }
126
127    public string GetSignatureForDocumentation ()
128    {
129      var s = Basename;
130
131      if (ExplicitInterface != null)
132        s = ExplicitInterface.GetSignatureForError () + "." + s;
133
134      if (Left == null)
135        return s;
136
137      return Left.GetSignatureForDocumentation () + "." + s;
138    }
139
140    public string GetSignatureForError ()
141    {
142      string s = TypeParameters == null ? null : "<" + TypeParameters.GetSignatureForError () + ">";
143      s = Name + s;
144
145      if (ExplicitInterface != null)
146        s = ExplicitInterface.GetSignatureForError () + "." + s;
147
148      if (Left == null)
149        return s;
150
151      return Left.GetSignatureForError () + "." + s;
152    }
153
154    public override bool Equals (object other)
155    {
156      return Equals (other as MemberName);
157    }
158
159    public bool Equals (MemberName other)
160    {
161      if (this == other)
162        return true;
163      if (other == null || Name != other.Name)
164        return false;
165
166      if ((TypeParameters != null) &&
167          (other.TypeParameters == null || TypeParameters.Count != other.TypeParameters.Count))
168        return false;
169
170      if ((TypeParameters == null) && (other.TypeParameters != null))
171        return false;
172
173      if (Left == null)
174        return other.Left == null;
175
176      return Left.Equals (other.Left);
177    }
178
179    public override int GetHashCode ()
180    {
181      int hash = Name.GetHashCode ();
182      for (MemberName n = Left; n != null; n = n.Left)
183        hash ^= n.Name.GetHashCode ();
184
185      if (TypeParameters != null)
186        hash ^= TypeParameters.Count << 5;
187
188      return hash & 0x7FFFFFFF;
189    }
190
191    public static string MakeName (string name, TypeParameters args)
192    {
193      if (args == null)
194        return name;
195
196      return name + "`" + args.Count;
197    }
198
199    public static string MakeName (string name, int count)
200    {
201      return name + "`" + count;
202    }
203  }
204
205  public class SimpleMemberName
206  {
207    public string Value;
208    public Location Location;
209
210    public SimpleMemberName (string name, Location loc)
211    {
212      this.Value = name;
213      this.Location = loc;
214    }
215  }
216
217  /// <summary>
218  ///   Base representation for members.  This is used to keep track
219  ///   of Name, Location and Modifier flags, and handling Attributes.
220  /// </summary>
221  [System.Diagnostics.DebuggerDisplay ("{GetSignatureForError()}")]
222  public abstract class MemberCore : Attributable, IMemberContext, IMemberDefinition
223  {
224    string IMemberDefinition.Name {
225      get {
226        return member_name.Name;
227      }
228    }
229
230                // Is not readonly because of IndexerName attribute
231    private MemberName member_name;
232    public MemberName MemberName {
233      get { return member_name; }
234    }
235
236    /// <summary>
237    ///   Modifier flags that the user specified in the source code
238    /// </summary>
239    private Modifiers mod_flags;
240    public Modifiers ModFlags {
241      set {
242        mod_flags = value;
243        if ((value & Modifiers.COMPILER_GENERATED) != 0)
244          caching_flags = Flags.IsUsed | Flags.IsAssigned;
245      }
246      get {
247        return mod_flags;
248      }
249    }
250
251    public virtual ModuleContainer Module {
252      get {
253        return Parent.Module;
254      }
255    }
256
257    public /*readonly*/ TypeContainer Parent;
258
259    /// <summary>
260    ///   Location where this declaration happens
261    /// </summary>
262    public Location Location {
263      get { return member_name.Location; }
264    }
265
266    /// <summary>
267    ///   XML documentation comment
268    /// </summary>
269    protected string comment;
270
271    /// <summary>
272    ///   Represents header string for documentation comment
273    ///   for each member types.
274    /// </summary>
275    public abstract string DocCommentHeader { get; }
276
277    [Flags]
278    public enum Flags {
279      Obsolete_Undetected = 1,    // Obsolete attribute has not been detected yet
280      Obsolete = 1 << 1,      // Type has obsolete attribute
281      ClsCompliance_Undetected = 1 << 2,  // CLS Compliance has not been detected yet
282      ClsCompliant = 1 << 3,      // Type is CLS Compliant
283      CloseTypeCreated = 1 << 4,    // Tracks whether we have Closed the type
284      HasCompliantAttribute_Undetected = 1 << 5,  // Presence of CLSCompliantAttribute has not been detected
285      HasClsCompliantAttribute = 1 << 6,      // Type has CLSCompliantAttribute
286      ClsCompliantAttributeFalse = 1 << 7,      // Member has CLSCompliant(false)
287      Excluded_Undetected = 1 << 8,   // Conditional attribute has not been detected yet
288      Excluded = 1 << 9,          // Method is conditional
289      MethodOverloadsExist = 1 << 10,   // Test for duplication must be performed
290      IsUsed = 1 << 11,
291      IsAssigned = 1 << 12,       // Field is assigned
292      HasExplicitLayout = 1 << 13,
293      PartialDefinitionExists = 1 << 14,  // Set when corresponding partial method definition exists
294      HasStructLayout = 1 << 15,      // Has StructLayoutAttribute
295      HasInstanceConstructor = 1 << 16,
296      HasUserOperators = 1 << 17,
297      CanBeReused = 1 << 18,
298      InterfacesExpanded = 1 << 19
299    }
300
301    /// <summary>
302    ///   MemberCore flags at first detected then cached
303    /// </summary>
304    internal Flags caching_flags;
305
306    protected MemberCore (TypeContainer parent, MemberName name, Attributes attrs)
307    {
308      this.Parent = parent;
309      member_name = name;
310      caching_flags = Flags.Obsolete_Undetected | Flags.ClsCompliance_Undetected | Flags.HasCompliantAttribute_Undetected | Flags.Excluded_Undetected;
311      AddAttributes (attrs, this);
312    }
313
314    protected virtual void SetMemberName (MemberName new_name)
315    {
316      member_name = new_name;
317    }
318
319    public virtual void Accept (StructuralVisitor visitor)
320    {
321      visitor.Visit (this);
322    }
323
324    protected bool CheckAbstractAndExtern (bool has_block)
325    {
326      if (Parent.PartialContainer.Kind == MemberKind.Interface)
327        return true;
328
329      if (has_block) {
330        if ((ModFlags & Modifiers.EXTERN) != 0) {
331          Report.Error (179, Location, "`{0}' cannot declare a body because it is marked extern",
332            GetSignatureForError ());
333          return false;
334        }
335
336        if ((ModFlags & Modifiers.ABSTRACT) != 0) {
337          Report.Error (500, Location, "`{0}' cannot declare a body because it is marked abstract",
338            GetSignatureForError ());
339          return false;
340        }
341      } else {
342        if ((ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN | Modifiers.PARTIAL)) == 0 && !(Parent is Delegate)) {
343          if (Compiler.Settings.Version >= LanguageVersion.V_3) {
344            Property.PropertyMethod pm = this as Property.PropertyMethod;
345            if (pm is Indexer.GetIndexerMethod || pm is Indexer.SetIndexerMethod)
346              pm = null;
347
348            if (pm != null && pm.Property.AccessorSecond == null) {
349              Report.Error (840, Location,
350                "`{0}' must have a body because it is not marked abstract or extern. The property can be automatically implemented when you define both accessors",
351                GetSignatureForError ());
352              return false;
353            }
354          }
355
356          Report.Error (501, Location, "`{0}' must have a body because it is not marked abstract, extern, or partial",
357                        GetSignatureForError ());
358          return false;
359        }
360      }
361
362      return true;
363    }
364
365    protected void CheckProtectedModifier ()
366    {
367      if ((ModFlags & Modifiers.PROTECTED) == 0)
368        return;
369
370      if (Parent.PartialContainer.Kind == MemberKind.Struct) {
371        Report.Error (666, Location, "`{0}': Structs cannot contain protected members",
372          GetSignatureForError ());
373        return;
374      }
375
376      if ((Parent.ModFlags & Modifiers.STATIC) != 0) {
377        Report.Error (1057, Location, "`{0}': Static classes cannot contain protected members",
378          GetSignatureForError ());
379        return;
380      }
381
382      if ((Parent.ModFlags & Modifiers.SEALED) != 0 && (ModFlags & Modifiers.OVERRIDE) == 0 &&
383        !(this is Destructor)) {
384        Report.Warning (628, 4, Location, "`{0}': new protected member declared in sealed class",
385          GetSignatureForError ());
386        return;
387      }
388    }
389
390    public abstract bool Define ();
391
392    public virtual string DocComment {
393      get {
394        return comment;
395      }
396      set {
397        comment = value;
398      }
399    }
400
401    //
402    // Returns full member name for error message
403    //
404    public virtual string GetSignatureForError ()
405    {
406      var parent = Parent.GetSignatureForError ();
407      if (parent == null)
408        return member_name.GetSignatureForError ();
409
410      return parent + "." + member_name.GetSignatureForError ();
411    }
412
413    /// <summary>
414    /// Base Emit method. This is also entry point for CLS-Compliant verification.
415    /// </summary>
416    public virtual void Emit ()
417    {
418      if (!Compiler.Settings.VerifyClsCompliance)
419        return;
420
421      VerifyClsCompliance ();
422    }
423
424    public bool IsAvailableForReuse {
425      get {
426        return (caching_flags & Flags.CanBeReused) != 0;
427      }
428      set {
429        caching_flags = value ? (caching_flags | Flags.CanBeReused) : (caching_flags & ~Flags.CanBeReused);
430      }
431    }
432
433    public bool IsCompilerGenerated {
434      get {
435        if ((mod_flags & Modifiers.COMPILER_GENERATED) != 0)
436          return true;
437
438        return Parent != null && Parent.IsCompilerGenerated;
439      }
440    }
441
442    public bool IsImported {
443      get {
444        return false;
445      }
446    }
447
448    public virtual bool IsUsed {
449      get {
450        return (caching_flags & Flags.IsUsed) != 0;
451      }
452    }
453
454    protected Report Report {
455      get {
456        return Compiler.Report;
457      }
458    }
459
460    public void SetIsUsed ()
461    {
462      caching_flags |= Flags.IsUsed;
463    }
464
465    public void SetIsAssigned ()
466    {
467      caching_flags |= Flags.IsAssigned;
468    }
469
470    public virtual void SetConstraints (List<Constraints> constraints_list)
471    {
472      var tparams = member_name.TypeParameters;
473      if (tparams == null) {
474        Report.Error (80, Location, "Constraints are not allowed on non-generic declarations");
475        return;
476      }
477
478      foreach (var c in constraints_list) {
479        var tp = tparams.Find (c.TypeParameter.Value);
480        if (tp == null) {
481          Report.Error (699, c.Location, "`{0}': A constraint references nonexistent type parameter `{1}'",
482            GetSignatureForError (), c.TypeParameter.Value);
483          continue;
484        }
485
486        tp.Constraints = c;
487      }
488    }
489
490    /// <summary>
491    /// Returns instance of ObsoleteAttribute for this MemberCore
492    /// </summary>
493    public virtual ObsoleteAttribute GetAttributeObsolete ()
494    {
495      if ((caching_flags & (Flags.Obsolete_Undetected | Flags.Obsolete)) == 0)
496        return null;
497
498      caching_flags &= ~Flags.Obsolete_Undetected;
499
500      if (OptAttributes == null)
501        return null;
502
503      Attribute obsolete_attr = OptAttributes.Search (Module.PredefinedAttributes.Obsolete);
504      if (obsolete_attr == null)
505        return null;
506
507      caching_flags |= Flags.Obsolete;
508
509      ObsoleteAttribute obsolete = obsolete_attr.GetObsoleteAttribute ();
510      if (obsolete == null)
511        return null;
512
513      return obsolete;
514    }
515
516    /// <summary>
517    /// Checks for ObsoleteAttribute presence. It's used for testing of all non-types elements
518    /// </summary>
519    public virtual void CheckObsoleteness (Location loc)
520    {
521      ObsoleteAttribute oa = GetAttributeObsolete ();
522      if (oa != null)
523        AttributeTester.Report_ObsoleteMessage (oa, GetSignatureForError (), loc, Report);
524    }
525
526    //
527    // Checks whether the type P is as accessible as this member
528    //
529    public bool IsAccessibleAs (TypeSpec p)
530    {
531      //
532      // if M is private, its accessibility is the same as this declspace.
533      // we already know that P is accessible to T before this method, so we
534      // may return true.
535      //
536      if ((mod_flags & Modifiers.PRIVATE) != 0)
537        return true;
538
539      while (TypeManager.HasElementType (p))
540        p = TypeManager.GetElementType (p);
541
542      if (p.IsGenericParameter)
543        return true;
544
545      for (TypeSpec p_parent; p != null; p = p_parent) {
546        p_parent = p.DeclaringType;
547
548        if (p.IsGeneric) {
549          foreach (TypeSpec t in p.TypeArguments) {
550            if (!IsAccessibleAs (t))
551              return false;
552          }
553        }
554
555        var pAccess = p.Modifiers & Modifiers.AccessibilityMask;
556        if (pAccess == Modifiers.PUBLIC)
557          continue;
558
559        bool same_access_restrictions = false;
560        for (MemberCore mc = this; !same_access_restrictions && mc != null && mc.Parent != null; mc = mc.Parent) {
561          var al = mc.ModFlags & Modifiers.AccessibilityMask;
562          switch (pAccess) {
563          case Modifiers.INTERNAL:
564            if (al == Modifiers.PRIVATE || al == Modifiers.INTERNAL)
565              same_access_restrictions = p.MemberDefinition.IsInternalAsPublic (mc.Module.DeclaringAssembly);
566           
567            break;
568
569          case Modifiers.PROTECTED:
570            if (al == Modifiers.PROTECTED) {
571              same_access_restrictions = mc.Parent.PartialContainer.IsBaseTypeDefinition (p_parent);
572              break;
573            }
574
575            if (al == Modifiers.PRIVATE) {
576              //
577              // When type is private and any of its parents derives from
578              // protected type then the type is accessible
579              //
580              while (mc.Parent != null && mc.Parent.PartialContainer != null) {
581                if (mc.Parent.PartialContainer.IsBaseTypeDefinition (p_parent))
582                  same_access_restrictions = true;
583                mc = mc.Parent;
584              }
585            }
586           
587            break;
588
589          case Modifiers.PROTECTED | Modifiers.INTERNAL:
590            if (al == Modifiers.INTERNAL)
591              same_access_restrictions = p.MemberDefinition.IsInternalAsPublic (mc.Module.DeclaringAssembly);
592            else if (al == (Modifiers.PROTECTED | Modifiers.INTERNAL))
593              same_access_restrictions = mc.Parent.PartialContainer.IsBaseTypeDefinition (p_parent) && p.MemberDefinition.IsInternalAsPublic (mc.Module.DeclaringAssembly);
594            else
595              goto case Modifiers.PROTECTED;
596
597            break;
598
599          case Modifiers.PRIVATE:
600            //
601            // Both are private and share same parent
602            //
603            if (al == Modifiers.PRIVATE) {
604              var decl = mc.Parent;
605              do {
606                same_access_restrictions = decl.CurrentType.MemberDefinition == p_parent.MemberDefinition;
607              } while (!same_access_restrictions && !decl.PartialContainer.IsTopLevel && (decl = decl.Parent) != null);
608            }
609           
610            break;
611           
612          default:
613            throw new InternalErrorException (al.ToString ());
614          }
615        }
616       
617        if (!same_access_restrictions)
618          return false;
619      }
620
621      return true;
622    }
623
624    /// <summary>
625    /// Analyze whether CLS-Compliant verification must be execute for this MemberCore.
626    /// </summary>
627    public override bool IsClsComplianceRequired ()
628    {
629      if ((caching_flags & Flags.ClsCompliance_Undetected) == 0)
630        return (caching_flags & Flags.ClsCompliant) != 0;
631
632      caching_flags &= ~Flags.ClsCompliance_Undetected;
633
634      if (HasClsCompliantAttribute) {
635        if ((caching_flags & Flags.ClsCompliantAttributeFalse) != 0)
636          return false;
637
638        caching_flags |= Flags.ClsCompliant;
639        return true;
640      }
641
642      if (Parent.IsClsComplianceRequired ()) {
643        caching_flags |= Flags.ClsCompliant;
644        return true;
645      }
646
647      return false;
648    }
649
650    public virtual string[] ConditionalConditions ()
651    {
652      return null;
653    }
654
655    /// <summary>
656    /// Returns true when MemberCore is exposed from assembly.
657    /// </summary>
658    public bool IsExposedFromAssembly ()
659    {
660      if ((ModFlags & (Modifiers.PUBLIC | Modifiers.PROTECTED)) == 0)
661        return this is NamespaceContainer;
662     
663      var parentContainer = Parent.PartialContainer;
664      while (parentContainer != null) {
665        if ((parentContainer.ModFlags & (Modifiers.PUBLIC | Modifiers.PROTECTED)) == 0)
666          return false;
667
668        parentContainer = parentContainer.Parent.PartialContainer;
669      }
670
671      return true;
672    }
673
674    //
675    // Does extension methods look up to find a method which matches name and extensionType.
676    // Search starts from this namespace and continues hierarchically up to top level.
677    //
678    public ExtensionMethodCandidates LookupExtensionMethod (TypeSpec extensionType, string name, int arity)
679    {
680      var m = Parent;
681      do {
682        var ns = m as NamespaceContainer;
683        if (ns != null)
684          return ns.LookupExtensionMethod (this, extensionType, name, arity, 0);
685
686        m = m.Parent;
687      } while (m != null);
688
689      return null;
690    }
691
692    public virtual FullNamedExpression LookupNamespaceAlias (string name)
693    {
694      return Parent.LookupNamespaceAlias (name);
695    }
696
697    public virtual FullNamedExpression LookupNamespaceOrType (string name, int arity, LookupMode mode, Location loc)
698    {
699      return Parent.LookupNamespaceOrType (name, arity, mode, loc);
700    }
701
702    /// <summary>
703    /// Goes through class hierarchy and gets value of first found CLSCompliantAttribute.
704    /// If no is attribute exists then assembly CLSCompliantAttribute is returned.
705    /// </summary>
706    public bool? CLSAttributeValue {
707      get {
708        if ((caching_flags & Flags.HasCompliantAttribute_Undetected) == 0) {
709          if ((caching_flags & Flags.HasClsCompliantAttribute) == 0)
710            return null;
711
712          return (caching_flags & Flags.ClsCompliantAttributeFalse) == 0;
713        }
714
715        caching_flags &= ~Flags.HasCompliantAttribute_Undetected;
716
717        if (OptAttributes != null) {
718          Attribute cls_attribute = OptAttributes.Search (Module.PredefinedAttributes.CLSCompliant);
719          if (cls_attribute != null) {
720            caching_flags |= Flags.HasClsCompliantAttribute;
721            if (cls_attribute.GetClsCompliantAttributeValue ())
722              return true;
723
724            caching_flags |= Flags.ClsCompliantAttributeFalse;
725            return false;
726          }
727        }
728
729        return null;
730      }
731    }
732
733    /// <summary>
734    /// Returns true if MemberCore is explicitly marked with CLSCompliantAttribute
735    /// </summary>
736    protected bool HasClsCompliantAttribute {
737      get {
738        return CLSAttributeValue.HasValue;
739      }
740    }
741
742    /// <summary>
743    /// Returns true when a member supports multiple overloads (methods, indexers, etc)
744    /// </summary>
745    public virtual bool EnableOverloadChecks (MemberCore overload)
746    {
747      return false;
748    }
749
750    /// <summary>
751    /// The main virtual method for CLS-Compliant verifications.
752    /// The method returns true if member is CLS-Compliant and false if member is not
753    /// CLS-Compliant which means that CLS-Compliant tests are not necessary. A descendants override it
754    /// and add their extra verifications.
755    /// </summary>
756    protected virtual bool VerifyClsCompliance ()
757    {
758      if (HasClsCompliantAttribute) {
759        if (!Module.DeclaringAssembly.HasCLSCompliantAttribute) {
760          Attribute a = OptAttributes.Search (Module.PredefinedAttributes.CLSCompliant);
761          if ((caching_flags & Flags.ClsCompliantAttributeFalse) != 0) {
762            Report.Warning (3021, 2, a.Location,
763              "`{0}' does not need a CLSCompliant attribute because the assembly is not marked as CLS-compliant",
764              GetSignatureForError ());
765          } else {
766            Report.Warning (3014, 1, a.Location,
767              "`{0}' cannot be marked as CLS-compliant because the assembly is not marked as CLS-compliant",
768              GetSignatureForError ());
769          }
770          return false;
771        }
772
773        if (!IsExposedFromAssembly ()) {
774          Attribute a = OptAttributes.Search (Module.PredefinedAttributes.CLSCompliant);
775          Report.Warning (3019, 2, a.Location, "CLS compliance checking will not be performed on `{0}' because it is not visible from outside this assembly", GetSignatureForError ());
776          return false;
777        }
778
779        if ((caching_flags & Flags.ClsCompliantAttributeFalse) != 0) {
780          if (Parent is Interface && Parent.IsClsComplianceRequired ()) {
781            Report.Warning (3010, 1, Location, "`{0}': CLS-compliant interfaces must have only CLS-compliant members", GetSignatureForError ());
782          } else if (Parent.Kind == MemberKind.Class && (ModFlags & Modifiers.ABSTRACT) != 0 && Parent.IsClsComplianceRequired ()) {
783            Report.Warning (3011, 1, Location, "`{0}': only CLS-compliant members can be abstract", GetSignatureForError ());
784          }
785
786          return false;
787        }
788
789        if (Parent.Kind != MemberKind.Namespace && Parent.Kind != 0 && !Parent.IsClsComplianceRequired ()) {
790          Attribute a = OptAttributes.Search (Module.PredefinedAttributes.CLSCompliant);
791          Report.Warning (3018, 1, a.Location, "`{0}' cannot be marked as CLS-compliant because it is a member of non CLS-compliant type `{1}'",
792            GetSignatureForError (), Parent.GetSignatureForError ());
793          return false;
794        }
795      } else {
796        if (!IsExposedFromAssembly ())
797          return false;
798
799        if (!Parent.IsClsComplianceRequired ())
800          return false;
801      }
802
803      if (member_name.Name [0] == '_') {
804        Warning_IdentifierNotCompliant ();
805      }
806
807      if (member_name.TypeParameters != null)
808        member_name.TypeParameters.VerifyClsCompliance ();
809
810      return true;
811    }
812
813    protected void Warning_IdentifierNotCompliant ()
814    {
815      Report.Warning (3008, 1, MemberName.Location, "Identifier `{0}' is not CLS-compliant", GetSignatureForError ());
816    }
817
818    public virtual string GetCallerMemberName ()
819    {
820      return MemberName.Name;
821    }
822
823    //
824    // Returns a string that represents the signature for this
825    // member which should be used in XML documentation.
826    //
827    public abstract string GetSignatureForDocumentation ();
828
829    public virtual void GetCompletionStartingWith (string prefix, List<string> results)
830    {
831      Parent.GetCompletionStartingWith (prefix, results);
832    }
833
834    //
835    // Generates xml doc comments (if any), and if required,
836    // handle warning report.
837    //
838    internal virtual void GenerateDocComment (DocumentationBuilder builder)
839    {
840      if (DocComment == null) {
841        if (IsExposedFromAssembly ()) {
842          Constructor c = this as Constructor;
843          if (c == null || !c.IsDefault ())
844            Report.Warning (1591, 4, Location,
845              "Missing XML comment for publicly visible type or member `{0}'", GetSignatureForError ());
846        }
847
848        return;
849      }
850
851      try {
852        builder.GenerateDocumentationForMember (this);
853      } catch (Exception e) {
854        throw new InternalErrorException (this, e);
855      }
856    }
857
858    public virtual void WriteDebugSymbol (MonoSymbolFile file)
859    {
860    }
861
862    #region IMemberContext Members
863
864    public virtual CompilerContext Compiler {
865      get {
866        return Module.Compiler;
867      }
868    }
869
870    public virtual TypeSpec CurrentType {
871      get { return Parent.CurrentType; }
872    }
873
874    public MemberCore CurrentMemberDefinition {
875      get { return this; }
876    }
877
878    public virtual TypeParameters CurrentTypeParameters {
879      get { return null; }
880    }
881
882    public bool IsObsolete {
883      get {
884        if (GetAttributeObsolete () != null)
885          return true;
886
887        return Parent != null && Parent.IsObsolete;
888      }
889    }
890
891    public bool IsUnsafe {
892      get {
893        if ((ModFlags & Modifiers.UNSAFE) != 0)
894          return true;
895
896        return Parent != null && Parent.IsUnsafe;
897      }
898    }
899
900    public bool IsStatic {
901      get {
902        return (ModFlags & Modifiers.STATIC) != 0;
903      }
904    }
905
906    #endregion
907  }
908
909  //
910  // Base member specification. A member specification contains
911  // member details which can alter in the context (e.g. generic instances)
912  //
913  public abstract class MemberSpec
914  {
915    [Flags]
916    public enum StateFlags
917    {
918      Obsolete_Undetected = 1,  // Obsolete attribute has not been detected yet
919      Obsolete = 1 << 1,      // Member has obsolete attribute
920      CLSCompliant_Undetected = 1 << 2, // CLSCompliant attribute has not been detected yet
921      CLSCompliant = 1 << 3,    // Member is CLS Compliant
922      MissingDependency_Undetected = 1 << 4,
923      MissingDependency = 1 << 5,
924      HasDynamicElement = 1 << 6,
925      ConstraintsChecked = 1 << 7,
926
927      IsAccessor = 1 << 9,    // Method is an accessor
928      IsGeneric = 1 << 10,    // Member contains type arguments
929
930      PendingMetaInflate = 1 << 12,
931      PendingMakeMethod = 1 << 13,
932      PendingMemberCacheMembers = 1 << 14,
933      PendingBaseTypeInflate = 1 << 15,
934      InterfacesExpanded = 1 << 16,
935      IsNotCSharpCompatible = 1 << 17,
936      SpecialRuntimeType = 1 << 18,
937      InflatedExpressionType = 1 << 19,
938      InflatedNullableType = 1 << 20,
939      GenericIterateInterface = 1 << 21,
940      GenericTask = 1 << 22,
941      InterfacesImported = 1 << 23,
942    }
943
944    //
945    // Some flags can be copied directly from other member
946    //
947    protected const StateFlags SharedStateFlags =
948      StateFlags.CLSCompliant | StateFlags.CLSCompliant_Undetected |
949      StateFlags.Obsolete | StateFlags.Obsolete_Undetected |
950      StateFlags.MissingDependency | StateFlags.MissingDependency_Undetected |
951      StateFlags.HasDynamicElement;
952
953    protected Modifiers modifiers;
954    public StateFlags state;
955    protected IMemberDefinition definition;
956    public readonly MemberKind Kind;
957    protected TypeSpec declaringType;
958
959#if DEBUG
960    static int counter;
961    public int ID = counter++;
962#endif
963
964    protected MemberSpec (MemberKind kind, TypeSpec declaringType, IMemberDefinition definition, Modifiers modifiers)
965    {
966      this.Kind = kind;
967      this.declaringType = declaringType;
968      this.definition = definition;
969      this.modifiers = modifiers;
970
971      if (kind == MemberKind.MissingType)
972        state = StateFlags.MissingDependency;
973      else
974        state = StateFlags.Obsolete_Undetected | StateFlags.CLSCompliant_Undetected | StateFlags.MissingDependency_Undetected;
975    }
976
977    #region Properties
978
979    public virtual int Arity {
980      get {
981        return 0;
982      }
983    }
984
985    public TypeSpec DeclaringType {
986      get {
987        return declaringType;
988      }
989      set {
990        declaringType = value;
991      }
992    }
993
994    public IMemberDefinition MemberDefinition {
995      get {
996        return definition;
997      }
998    }
999
1000    public Modifiers Modifiers {
1001      get {
1002        return modifiers;
1003      }
1004      set {
1005        modifiers = value;
1006      }
1007    }
1008   
1009    public virtual string Name {
1010      get {
1011        return definition.Name;
1012      }
1013    }
1014
1015    public bool IsAbstract {
1016      get { return (modifiers & Modifiers.ABSTRACT) != 0; }
1017    }
1018
1019    public bool IsAccessor {
1020      get {
1021        return (state & StateFlags.IsAccessor) != 0;
1022      }
1023      set {
1024        state = value ? state | StateFlags.IsAccessor : state & ~StateFlags.IsAccessor;
1025      }
1026    }
1027
1028    //
1029    // Return true when this member is a generic in C# terms
1030    // A nested non-generic type of generic type will return false
1031    //
1032    public bool IsGeneric {
1033      get {
1034        return (state & StateFlags.IsGeneric) != 0;
1035      }
1036      set {
1037        state = value ? state | StateFlags.IsGeneric : state & ~StateFlags.IsGeneric;
1038      }
1039    }
1040
1041    //
1042    // Returns true for imported members which are not compatible with C# language
1043    //
1044    public bool IsNotCSharpCompatible {
1045      get {
1046        return (state & StateFlags.IsNotCSharpCompatible) != 0;
1047      }
1048      set {
1049        state = value ? state | StateFlags.IsNotCSharpCompatible : state & ~StateFlags.IsNotCSharpCompatible;
1050      }
1051    }
1052
1053    public bool IsPrivate {
1054      get { return (modifiers & Modifiers.PRIVATE) != 0; }
1055    }
1056
1057    public bool IsPublic {
1058      get { return (modifiers & Modifiers.PUBLIC) != 0; }
1059    }
1060
1061    public bool IsStatic {
1062      get {
1063        return (modifiers & Modifiers.STATIC) != 0;
1064      }
1065    }
1066
1067    #endregion
1068
1069    public virtual ObsoleteAttribute GetAttributeObsolete ()
1070    {
1071      if ((state & (StateFlags.Obsolete | StateFlags.Obsolete_Undetected)) == 0)
1072        return null;
1073
1074      state &= ~StateFlags.Obsolete_Undetected;
1075
1076      var oa = definition.GetAttributeObsolete ();
1077      if (oa != null)
1078        state |= StateFlags.Obsolete;
1079
1080      return oa;
1081    }
1082
1083    //
1084    // Returns a list of missing dependencies of this member. The list
1085    // will contain types only but it can have numerous values for members
1086    // like methods where both return type and all parameters are checked
1087    //
1088    public List<MissingTypeSpecReference> GetMissingDependencies ()
1089    {
1090      return GetMissingDependencies (this);
1091    }
1092
1093    public List<MissingTypeSpecReference> GetMissingDependencies (MemberSpec caller)
1094    {
1095      if ((state & (StateFlags.MissingDependency | StateFlags.MissingDependency_Undetected)) == 0)
1096        return null;
1097
1098      state &= ~StateFlags.MissingDependency_Undetected;
1099
1100      var imported = definition as ImportedDefinition;
1101      List<MissingTypeSpecReference> missing;
1102      if (imported != null) {
1103        missing = ResolveMissingDependencies (caller);
1104      } else if (this is ElementTypeSpec) {
1105        missing = ((ElementTypeSpec) this).Element.GetMissingDependencies (caller);
1106      } else {
1107        missing = null;
1108      }
1109
1110      if (missing != null) {
1111        state |= StateFlags.MissingDependency;
1112      }
1113
1114      return missing;
1115    }
1116
1117    public abstract List<MissingTypeSpecReference> ResolveMissingDependencies (MemberSpec caller);
1118
1119    protected virtual bool IsNotCLSCompliant (out bool attrValue)
1120    {
1121      var cls = MemberDefinition.CLSAttributeValue;
1122      attrValue = cls ?? false;
1123      return cls == false;
1124    }
1125
1126    public virtual string GetSignatureForDocumentation ()
1127    {
1128      return DeclaringType.GetSignatureForDocumentation () + "." + Name;
1129    }
1130
1131    public virtual string GetSignatureForError ()
1132    {
1133      var bf = MemberDefinition as Property.BackingField;
1134      string name;
1135      if (bf == null) {
1136        name = Name;
1137      } else {
1138        name = bf.OriginalProperty.MemberName.Name;
1139      }
1140
1141      return DeclaringType.GetSignatureForError () + "." + name;
1142    }
1143
1144    public virtual MemberSpec InflateMember (TypeParameterInflator inflator)
1145    {
1146      var inflated = (MemberSpec) MemberwiseClone ();
1147      inflated.declaringType = inflator.TypeInstance;
1148      if (DeclaringType.IsGenericOrParentIsGeneric)
1149        inflated.state |= StateFlags.PendingMetaInflate;
1150#if DEBUG
1151      inflated.ID += 1000000;
1152#endif
1153      return inflated;
1154    }
1155
1156    //
1157    // Is this member accessible from invocation context
1158    //
1159    public bool IsAccessible (IMemberContext ctx)
1160    {
1161      var ma = Modifiers & Modifiers.AccessibilityMask;
1162      if (ma == Modifiers.PUBLIC)
1163        return true;
1164
1165      var parentType = /* this as TypeSpec ?? */ DeclaringType;
1166      var ctype = ctx.CurrentType;
1167
1168      if (ma == Modifiers.PRIVATE) {
1169        if (ctype == null || parentType == null)
1170          return false;
1171        //
1172        // It's only accessible to the current class or children
1173        //
1174        if (parentType.MemberDefinition == ctype.MemberDefinition)
1175          return true;
1176
1177        return TypeManager.IsNestedChildOf (ctype, parentType.MemberDefinition);
1178      }
1179
1180      if ((ma & Modifiers.INTERNAL) != 0) {
1181        bool b;
1182        var assembly = ctype == null ? ctx.Module.DeclaringAssembly : ctype.MemberDefinition.DeclaringAssembly;
1183
1184        if (parentType == null) {
1185          b = ((ITypeDefinition) MemberDefinition).IsInternalAsPublic (assembly);
1186        } else {
1187          b = DeclaringType.MemberDefinition.IsInternalAsPublic (assembly);
1188        }
1189
1190        if (b || ma == Modifiers.INTERNAL)
1191          return b;
1192      }
1193
1194      //
1195      // Checks whether `ctype' is a subclass or nested child of `parentType'.
1196      //
1197      while (ctype != null) {
1198        if (TypeManager.IsFamilyAccessible (ctype, parentType))
1199          return true;
1200
1201        // Handle nested types.
1202        ctype = ctype.DeclaringType;  // TODO: Untested ???
1203      }
1204
1205      return false;
1206    }
1207
1208    //
1209    // Returns member CLS compliance based on full member hierarchy
1210    //
1211    public bool IsCLSCompliant ()
1212    {
1213      if ((state & StateFlags.CLSCompliant_Undetected) != 0) {
1214        state &= ~StateFlags.CLSCompliant_Undetected;
1215
1216        bool compliant;
1217        if (IsNotCLSCompliant (out compliant))
1218          return false;
1219
1220        if (!compliant) {
1221          if (DeclaringType != null) {
1222            compliant = DeclaringType.IsCLSCompliant ();
1223          } else {
1224            compliant = ((ITypeDefinition) MemberDefinition).DeclaringAssembly.IsCLSCompliant;
1225          }
1226        }
1227
1228        if (compliant)
1229          state |= StateFlags.CLSCompliant;
1230      }
1231
1232      return (state & StateFlags.CLSCompliant) != 0;
1233    }
1234
1235    public bool IsConditionallyExcluded (IMemberContext ctx)
1236    {
1237      if ((Kind & (MemberKind.Class | MemberKind.Method)) == 0)
1238        return false;
1239
1240      var conditions = MemberDefinition.ConditionalConditions ();
1241      if (conditions == null)
1242        return false;
1243
1244      var m = ctx.CurrentMemberDefinition;
1245      CompilationSourceFile unit = null;
1246      while (m != null && unit == null) {
1247        unit = m as CompilationSourceFile;
1248        m = m.Parent;
1249      }
1250
1251      if (unit != null) {
1252        foreach (var condition in conditions) {
1253          if (unit.IsConditionalDefined (condition))
1254            return false;
1255        }
1256      }
1257
1258      return true;
1259    }
1260
1261    public override string ToString ()
1262    {
1263      return GetSignatureForError ();
1264    }
1265  }
1266
1267  //
1268  // Member details which are same between all member
1269  // specifications
1270  //
1271  public interface IMemberDefinition
1272  {
1273    bool? CLSAttributeValue { get; }
1274    string Name { get; }
1275    bool IsImported { get; }
1276
1277    string[] ConditionalConditions ();
1278    ObsoleteAttribute GetAttributeObsolete ();
1279    void SetIsAssigned ();
1280    void SetIsUsed ();
1281  }
1282
1283  public interface IMethodDefinition : IMemberDefinition
1284  {
1285    MethodBase Metadata { get; }
1286  }
1287
1288  public interface IParametersMember : IInterfaceMemberSpec
1289  {
1290    AParametersCollection Parameters { get; }
1291  }
1292
1293  public interface IInterfaceMemberSpec
1294  {
1295    TypeSpec MemberType { get; }
1296  }
1297}
Note: See TracBrowser for help on using the repository browser.