Emit correct sequence info for iterators
[mono.git] / mcs / mcs / decl.cs
index 6ac4a971b705e131fb9d526ac040cffd331d535c..7cda8d43c43b634a1970b5ea6193a1014bf1b258 100644 (file)
@@ -15,6 +15,7 @@
 using System;
 using System.Collections.Generic;
 using System.Diagnostics;
+using System.Text;
 
 #if NET_2_1
 using XmlElement = System.Object;
@@ -90,12 +91,6 @@ namespace Mono.CSharp {
                        this.Left = left;
                }
 
-               // TODO: Remove
-               public string GetName ()
-               {
-                       return GetName (false);
-               }
-
                public int Arity {
                        get {
                                return TypeParameters == null ? 0 : TypeParameters.Count;
@@ -104,24 +99,10 @@ namespace Mono.CSharp {
 
                public bool IsGeneric {
                        get {
-                               if (TypeParameters != null)
-                                       return true;
-                               else if (Left != null)
-                                       return Left.IsGeneric;
-                               else
-                                       return false;
+                               return TypeParameters != null;
                        }
                }
 
-               public string GetName (bool is_generic)
-               {
-                       string name = is_generic ? Basename : Name;
-                       if (Left != null)
-                               return Left.GetName (is_generic) + "." + name;
-
-                       return name;
-               }
-
                public string Basename {
                        get {
                                if (TypeParameters != null)
@@ -130,6 +111,31 @@ namespace Mono.CSharp {
                        }
                }
 
+               public void CreateMetadataName (StringBuilder sb)
+               {
+                       if (Left != null)
+                               Left.CreateMetadataName (sb);
+
+                       if (sb.Length != 0) {
+                               sb.Append (".");
+                       }
+
+                       sb.Append (Basename);
+               }
+
+               public string GetSignatureForDocumentation ()
+               {
+                       var s = Basename;
+
+                       if (ExplicitInterface != null)
+                               s = ExplicitInterface.GetSignatureForError () + "." + s;
+
+                       if (Left == null)
+                               return s;
+
+                       return Left.GetSignatureForDocumentation () + "." + s;
+               }
+
                public string GetSignatureForError ()
                {
                        string s = TypeParameters == null ? null : "<" + TypeParameters.GetSignatureForError () + ">";
@@ -214,20 +220,6 @@ namespace Mono.CSharp {
        [System.Diagnostics.DebuggerDisplay ("{GetSignatureForError()}")]
        public abstract class MemberCore : Attributable, IMemberContext, IMemberDefinition
        {
-               /// <summary>
-               ///   Public name
-               /// </summary>
-
-               protected string cached_name;
-               // TODO: Remove in favor of MemberName
-               public string Name {
-                       get {
-                               if (cached_name == null)
-                                       cached_name = MemberName.GetName (!(this is GenericMethod) && !(this is Method));
-                               return cached_name;
-                       }
-               }
-
                string IMemberDefinition.Name {
                        get {
                                return member_name.Name;
@@ -298,7 +290,9 @@ namespace Mono.CSharp {
                        IsAssigned = 1 << 12,                           // Field is assigned
                        HasExplicitLayout       = 1 << 13,
                        PartialDefinitionExists = 1 << 14,      // Set when corresponding partial method definition exists
-                       HasStructLayout         = 1 << 15                       // Has StructLayoutAttribute
+                       HasStructLayout = 1 << 15,                      // Has StructLayoutAttribute
+                       HasInstanceConstructor = 1 << 16,
+                       HasUserOperators = 1 << 17
                }
 
                /// <summary>
@@ -306,9 +300,9 @@ namespace Mono.CSharp {
                /// </summary>
                internal Flags caching_flags;
 
-               public MemberCore (DeclSpace parent, MemberName name, Attributes attrs)
+               public MemberCore (TypeContainer parent, MemberName name, Attributes attrs)
                {
-                       this.Parent = parent as TypeContainer;
+                       this.Parent = parent;
                        member_name = name;
                        caching_flags = Flags.Obsolete_Undetected | Flags.ClsCompliance_Undetected | Flags.HasCompliantAttribute_Undetected | Flags.Excluded_Undetected;
                        AddAttributes (attrs, this);
@@ -317,7 +311,6 @@ namespace Mono.CSharp {
                protected virtual void SetMemberName (MemberName new_name)
                {
                        member_name = new_name;
-                       cached_name = null;
                }
 
                public virtual void Accept (StructuralVisitor visitor)
@@ -407,10 +400,11 @@ namespace Mono.CSharp {
                //
                public virtual string GetSignatureForError ()
                {
-                       if (Parent == null || Parent.Parent == null)
+                       var parent = Parent.GetSignatureForError ();
+                       if (parent == null)
                                return member_name.GetSignatureForError ();
 
-                       return Parent.GetSignatureForError () + "." + member_name.GetSignatureForError ();
+                       return parent + "." + member_name.GetSignatureForError ();
                }
 
                /// <summary>
@@ -461,6 +455,26 @@ namespace Mono.CSharp {
                        caching_flags |= Flags.IsAssigned;
                }
 
+               public void SetConstraints (List<Constraints> constraints_list)
+               {
+                       var tparams = member_name.TypeParameters;
+                       if (tparams == null) {
+                               Report.Error (80, Location, "Constraints are not allowed on non-generic declarations");
+                               return;
+                       }
+
+                       foreach (var c in constraints_list) {
+                               var tp = tparams.Find (c.TypeParameter.Value);
+                               if (tp == null) {
+                                       Report.Error (699, c.Location, "`{0}': A constraint references nonexistent type parameter `{1}'",
+                                               GetSignatureForError (), c.TypeParameter.Value);
+                                       continue;
+                               }
+
+                               tp.Constraints = c;
+                       }
+               }
+
                /// <summary>
                /// Returns instance of ObsoleteAttribute for this MemberCore
                /// </summary>
@@ -542,7 +556,7 @@ namespace Mono.CSharp {
 
                                        case Modifiers.PROTECTED:
                                                if (al == Modifiers.PROTECTED) {
-                                                       same_access_restrictions = mc.Parent.IsBaseTypeDefinition (p_parent);
+                                                       same_access_restrictions = mc.Parent.PartialContainer.IsBaseTypeDefinition (p_parent);
                                                        break;
                                                }
 
@@ -551,8 +565,8 @@ namespace Mono.CSharp {
                                                        // When type is private and any of its parents derives from
                                                        // protected type then the type is accessible
                                                        //
-                                                       while (mc.Parent != null) {
-                                                               if (mc.Parent.IsBaseTypeDefinition (p_parent))
+                                                       while (mc.Parent != null && mc.Parent.PartialContainer != null) {
+                                                               if (mc.Parent.PartialContainer.IsBaseTypeDefinition (p_parent))
                                                                        same_access_restrictions = true;
                                                                mc = mc.Parent; 
                                                        }
@@ -564,7 +578,7 @@ namespace Mono.CSharp {
                                                if (al == Modifiers.INTERNAL)
                                                        same_access_restrictions = p.MemberDefinition.IsInternalAsPublic (mc.Module.DeclaringAssembly);
                                                else if (al == (Modifiers.PROTECTED | Modifiers.INTERNAL))
-                                                       same_access_restrictions = mc.Parent.IsBaseTypeDefinition (p_parent) && p.MemberDefinition.IsInternalAsPublic (mc.Module.DeclaringAssembly);
+                                                       same_access_restrictions = mc.Parent.PartialContainer.IsBaseTypeDefinition (p_parent) && p.MemberDefinition.IsInternalAsPublic (mc.Module.DeclaringAssembly);
                                                else
                                                        goto case Modifiers.PROTECTED;
 
@@ -578,7 +592,7 @@ namespace Mono.CSharp {
                                                        var decl = mc.Parent;
                                                        do {
                                                                same_access_restrictions = decl.CurrentType == p_parent;
-                                                       } while (!same_access_restrictions && !decl.IsTopLevel && (decl = decl.Parent) != null);
+                                                       } while (!same_access_restrictions && !decl.PartialContainer.IsTopLevel && (decl = decl.Parent) != null);
                                                }
                                                
                                                break;
@@ -613,7 +627,7 @@ namespace Mono.CSharp {
                                return true;
                        }
 
-                       if (Parent.PartialContainer.IsClsComplianceRequired ()) {
+                       if (Parent.IsClsComplianceRequired ()) {
                                caching_flags |= Flags.ClsCompliant;
                                return true;
                        }
@@ -632,25 +646,40 @@ namespace Mono.CSharp {
                public bool IsExposedFromAssembly ()
                {
                        if ((ModFlags & (Modifiers.PUBLIC | Modifiers.PROTECTED)) == 0)
-                               return false;
+                               return this is NamespaceContainer;
                        
-                       DeclSpace parentContainer = Parent.PartialContainer;
-                       while (parentContainer != null && parentContainer.ModFlags != 0) {
+                       var parentContainer = Parent.PartialContainer;
+                       while (parentContainer != null) {
                                if ((parentContainer.ModFlags & (Modifiers.PUBLIC | Modifiers.PROTECTED)) == 0)
                                        return false;
-                               parentContainer = parentContainer.Parent;
+
+                               parentContainer = parentContainer.Parent.PartialContainer;
                        }
+
                        return true;
                }
 
-               public virtual ExtensionMethodCandidates LookupExtensionMethod (TypeSpec extensionType, string name, int arity)
+               //
+               // Does extension methods look up to find a method which matches name and extensionType.
+               // Search starts from this namespace and continues hierarchically up to top level.
+               //
+               public ExtensionMethodCandidates LookupExtensionMethod (TypeSpec extensionType, string name, int arity)
                {
-                       return Parent.LookupExtensionMethod (extensionType, name, arity);
+                       var m = Parent;
+                       do {
+                               var ns = m as NamespaceContainer;
+                               if (ns != null)
+                                       return ns.LookupExtensionMethod (this, extensionType, name, arity, ns, 0);
+
+                               m = m.Parent;
+                       } while (m != null);
+
+                       return null;
                }
 
                public virtual FullNamedExpression LookupNamespaceAlias (string name)
                {
-                       return Parent.NamespaceEntry.LookupNamespaceAlias (name);
+                       return Parent.LookupNamespaceAlias (name);
                }
 
                public virtual FullNamedExpression LookupNamespaceOrType (string name, int arity, LookupMode mode, Location loc)
@@ -736,7 +765,7 @@ namespace Mono.CSharp {
                                }
 
                                if ((caching_flags & Flags.ClsCompliantAttributeFalse) != 0) {
-                                       if (Parent.Kind == MemberKind.Interface && Parent.IsClsComplianceRequired ()) {
+                                       if (Parent is Interface && Parent.IsClsComplianceRequired ()) {
                                                Report.Warning (3010, 1, Location, "`{0}': CLS-compliant interfaces must have only CLS-compliant members", GetSignatureForError ());
                                        } else if (Parent.Kind == MemberKind.Class && (ModFlags & Modifiers.ABSTRACT) != 0 && Parent.IsClsComplianceRequired ()) {
                                                Report.Warning (3011, 1, Location, "`{0}': only CLS-compliant members can be abstract", GetSignatureForError ());
@@ -745,7 +774,7 @@ namespace Mono.CSharp {
                                        return false;
                                }
 
-                               if (Parent.Parent != null && !Parent.IsClsComplianceRequired ()) {
+                               if (Parent.Kind != MemberKind.Namespace && Parent.Kind != 0 && !Parent.IsClsComplianceRequired ()) {
                                        Attribute a = OptAttributes.Search (Module.PredefinedAttributes.CLSCompliant);
                                        Report.Warning (3018, 1, a.Location, "`{0}' cannot be marked as CLS-compliant because it is a member of non CLS-compliant type `{1}'",
                                                GetSignatureForError (), Parent.GetSignatureForError ());
@@ -755,23 +784,36 @@ namespace Mono.CSharp {
                                if (!IsExposedFromAssembly ())
                                        return false;
 
-                               if (!Parent.PartialContainer.IsClsComplianceRequired ())
+                               if (!Parent.IsClsComplianceRequired ())
                                        return false;
                        }
 
                        if (member_name.Name [0] == '_') {
-                               Report.Warning (3008, 1, Location, "Identifier `{0}' is not CLS-compliant", GetSignatureForError () );
+                               Warning_IdentifierNotCompliant ();
                        }
 
+                       if (member_name.TypeParameters != null)
+                               member_name.TypeParameters.VerifyClsCompliance ();
+
                        return true;
                }
 
+               protected void Warning_IdentifierNotCompliant ()
+               {
+                       Report.Warning (3008, 1, MemberName.Location, "Identifier `{0}' is not CLS-compliant", GetSignatureForError ());
+               }
+
                //
                // Returns a string that represents the signature for this 
                // member which should be used in XML documentation.
                //
                public abstract string GetSignatureForDocumentation ();
 
+               public virtual void GetCompletionStartingWith (string prefix, List<string> results)
+               {
+                       Parent.GetCompletionStartingWith (prefix, results);
+               }
+
                //
                // Generates xml doc comments (if any), and if required,
                // handle warning report.
@@ -799,7 +841,9 @@ namespace Mono.CSharp {
                #region IMemberContext Members
 
                public virtual CompilerContext Compiler {
-                       get { return Parent.Compiler; }
+                       get {
+                               return Module.Compiler;
+                       }
                }
 
                public virtual TypeSpec CurrentType {
@@ -1048,7 +1092,13 @@ namespace Mono.CSharp {
                public virtual string GetSignatureForError ()
                {
                        var bf = MemberDefinition as Property.BackingField;
-                       var name = bf == null ? Name : bf.OriginalName;
+                       string name;
+                       if (bf == null) {
+                               name = Name;
+                       } else {
+                               name = bf.OriginalProperty.MemberName.Name;
+                       }
+
                        return DeclaringType.GetSignatureForError () + "." + name;
                }
 
@@ -1143,7 +1193,7 @@ namespace Mono.CSharp {
                        return (state & StateFlags.CLSCompliant) != 0;
                }
 
-               public bool IsConditionallyExcluded (CompilerContext ctx, Location loc)
+               public bool IsConditionallyExcluded (IMemberContext ctx, Location loc)
                {
                        if ((Kind & (MemberKind.Class | MemberKind.Method)) == 0)
                                return false;
@@ -1152,9 +1202,18 @@ namespace Mono.CSharp {
                        if (conditions == null)
                                return false;
 
-                       foreach (var condition in conditions) {
-                               if (loc.CompilationUnit.IsConditionalDefined (ctx, condition))
-                                       return false;
+                       var m = ctx.CurrentMemberDefinition;
+                       CompilationSourceFile unit = null;
+                       while (m != null && unit == null) {
+                               unit = m as CompilationSourceFile;
+                               m = m.Parent;
+                       }
+
+                       if (unit != null) {
+                               foreach (var condition in conditions) {
+                                       if (unit.IsConditionalDefined (condition))
+                                               return false;
+                               }
                        }
 
                        return true;
@@ -1191,225 +1250,4 @@ namespace Mono.CSharp {
        {
                TypeSpec MemberType { get; }
        }
-
-       //
-       // Base type container declaration. It exists to handle partial types
-       // which share same definition (PartialContainer) but have different
-       // resolve scopes
-       //
-       public abstract class DeclSpace : MemberCore {
-               /// <summary>
-               ///   This points to the actual definition that is being
-               ///   created with System.Reflection.Emit
-               /// </summary>
-               public TypeBuilder TypeBuilder;
-
-               //
-               // This is the namespace in which this typecontainer
-               // was declared.  We use this to resolve names.
-               //
-               public NamespaceContainer NamespaceEntry;
-
-               public readonly string Basename;
-               
-               protected Dictionary<string, MemberCore> defined_names;
-
-               public TypeContainer PartialContainer;
-
-               protected readonly bool is_generic;
-
-               //
-               // Whether we are Generic
-               //
-               public bool IsGeneric {
-                       get {
-                               if (is_generic)
-                                       return true;
-                               else if (Parent != null)
-                                       return Parent.IsGeneric;
-                               else
-                                       return false;
-                       }
-               }
-
-               static readonly string[] attribute_targets = new string [] { "type" };
-
-               public DeclSpace (NamespaceContainer ns, DeclSpace parent, MemberName name,
-                                 Attributes attrs)
-                       : base (parent, name, attrs)
-               {
-                       NamespaceEntry = ns;
-                       Basename = name.Basename;
-                       defined_names = new Dictionary<string, MemberCore> ();
-                       PartialContainer = null;
-                       if (name.TypeParameters != null) {
-                               is_generic = true;
-                       }
-               }
-
-               /// <summary>
-               /// Adds the member to defined_names table. It tests for duplications and enclosing name conflicts
-               /// </summary>
-               protected virtual bool AddToContainer (MemberCore symbol, string name)
-               {
-                       MemberCore mc;
-                       if (!defined_names.TryGetValue (name, out mc)) {
-                               defined_names.Add (name, symbol);
-                               return true;
-                       }
-
-                       if (((mc.ModFlags | symbol.ModFlags) & Modifiers.COMPILER_GENERATED) != 0)
-                               return true;
-
-                       if (symbol.EnableOverloadChecks (mc))
-                               return true;
-
-                       InterfaceMemberBase im = mc as InterfaceMemberBase;
-                       if (im != null && im.IsExplicitImpl)
-                               return true;
-
-                       Report.SymbolRelatedToPreviousError (mc);
-                       if ((mc.ModFlags & Modifiers.PARTIAL) != 0 && (symbol is ClassOrStruct || symbol is Interface)) {
-                               Error_MissingPartialModifier (symbol);
-                               return false;
-                       }
-
-                       if (symbol is TypeParameter) {
-                               Report.Error (692, symbol.Location,
-                                       "Duplicate type parameter `{0}'", symbol.GetSignatureForError ());
-                       } else {
-                               Report.Error (102, symbol.Location,
-                                       "The type `{0}' already contains a definition for `{1}'",
-                                       GetSignatureForError (), name);
-                       }
-
-                       return false;
-               }
-
-               protected void RemoveFromContainer (string name)
-               {
-                       defined_names.Remove (name);
-               }
-               
-               /// <summary>
-               ///   Returns the MemberCore associated with a given name in the declaration
-               ///   space. It doesn't return method based symbols !!
-               /// </summary>
-               /// 
-               public MemberCore GetDefinition (string name)
-               {
-                       MemberCore mc = null;
-                       defined_names.TryGetValue (name, out mc);
-                       return mc;
-               }
-       
-               // 
-               // root_types contains all the types.  All TopLevel types
-               // hence have a parent that points to `root_types', that is
-               // why there is a non-obvious test down here.
-               //
-               public bool IsTopLevel {
-                       get { return (Parent != null && Parent.Parent == null); }
-               }
-
-               public virtual bool IsUnmanagedType ()
-               {
-                       return false;
-               }
-
-               protected abstract TypeAttributes TypeAttr { get; }
-
-               /// <remarks>
-               ///  Should be overriten by the appropriate declaration space
-               /// </remarks>
-               public abstract void DefineType ();
-
-               protected void Error_MissingPartialModifier (MemberCore type)
-               {
-                       Report.Error (260, type.Location,
-                               "Missing partial modifier on declaration of type `{0}'. Another partial declaration of this type exists",
-                               type.GetSignatureForError ());
-               }
-
-               public override string GetSignatureForDocumentation ()
-               {
-                       return Name;
-               }
-
-               public override string GetSignatureForError ()
-               {
-                       return MemberName.GetSignatureForError ();
-               }
-
-               public virtual void SetParameterInfo (List<Constraints> constraints_list)
-               {
-                       if (!is_generic) {
-                               if (constraints_list != null) {
-                                       Report.Error (
-                                               80, Location, "Constraints are not allowed " +
-                                               "on non-generic declarations");
-                               }
-
-                               return;
-                       }
-
-                       //
-                       // Register all the names
-                       //
-                       for (int i = 0; i < MemberName.TypeParameters.Count; i++) {
-                               var name = MemberName.TypeParameters [i];
-
-                               Constraints constraints = null;
-                               if (constraints_list != null) {
-                                       int total = constraints_list.Count;
-                                       for (int ii = 0; ii < total; ++ii) {
-                                               Constraints constraints_at = constraints_list[ii];
-                                               // TODO: it is used by iterators only
-                                               if (constraints_at == null) {
-                                                       constraints_list.RemoveAt (ii);
-                                                       --total;
-                                                       continue;
-                                               }
-                                               if (constraints_at.TypeParameter.Value == name.MemberName.Name) {
-                                                       constraints = constraints_at;
-                                                       constraints_list.RemoveAt(ii);
-                                                       break;
-                                               }
-                                       }
-                               }
-
-                               if (name.Variance != Variance.None && !(this is Delegate || this is Interface)) {
-                                       Report.Error (1960, name.Location, "Variant type parameters can only be used with interfaces and delegates");
-                               }
-
-                               MemberName.TypeParameters[i].Constraints = constraints;
-                               if (name.MemberName != null)
-                                       AddToContainer (name, name.MemberName.Name);
-                       }
-
-                       if (constraints_list != null && constraints_list.Count > 0) {
-                               foreach (Constraints constraint in constraints_list) {
-                                       Report.Error(699, constraint.Location, "`{0}': A constraint references nonexistent type parameter `{1}'", 
-                                               GetSignatureForError (), constraint.TypeParameter.Value);
-                               }
-                       }
-               }
-
-               public override string[] ValidAttributeTargets {
-                       get { return attribute_targets; }
-               }
-
-               protected override bool VerifyClsCompliance ()
-               {
-                       if (!base.VerifyClsCompliance ()) {
-                               return false;
-                       }
-
-                       if (CurrentTypeParameters != null) {
-                               CurrentTypeParameters.VerifyClsCompliance ();
-                       }
-
-                       return true;
-               }
-       }
 }