2002-11-16 Martin Baulig <martin@ximian.com>
[mono.git] / mcs / mcs / interface.cs
index b94dc9caa5cef65050aa7c2e131e74bd0bdf8fd4..2c5b939f41e93f6902ef39ac9182bc7e6281993e 100755 (executable)
@@ -7,7 +7,7 @@
 //
 // (C) 2001 Ximian, Inc (http://www.ximian.com)
 //
-
+#define CACHE
 using System.Collections;
 using System;
 using System.IO;
@@ -19,7 +19,7 @@ namespace Mono.CSharp {
        /// <summary>
        ///   Interfaces
        /// </summary>
-       public class Interface : DeclSpace {
+       public class Interface : DeclSpace, IMemberContainer {
                const MethodAttributes interface_method_attributes =
                        MethodAttributes.Public |
                        MethodAttributes.Abstract |
@@ -50,6 +50,11 @@ namespace Mono.CSharp {
 
                public string IndexerName;
 
+               IMemberContainer parent_container;
+               MemberCache member_cache;
+
+               bool members_defined;
+
                // These will happen after the semantic analysis
                
                // Hashtable defined_indexers;
@@ -225,9 +230,22 @@ namespace Mono.CSharp {
                        return true;
                }
 
-               public MethodInfo [] GetMethods ()
+               //
+               // This might trigger a definition of the methods.  This happens only
+               // with Attributes, as Attribute classes are processed before interfaces.
+               // Ideally, we should make everything just define recursively in terms
+               // of its dependencies.
+               //
+               public MethodInfo [] GetMethods (TypeContainer container)
                {
-                       int n = method_builders.Count;
+                       int n = 0;
+                       
+                       if (!members_defined){
+                               if (DefineMembers (container))
+                                       n = method_builders.Count;
+                       } else
+                               n = method_builders.Count;
+                       
                        MethodInfo [] mi = new MethodInfo [n];
                        
                        method_builders.CopyTo (mi, 0);
@@ -236,7 +254,8 @@ namespace Mono.CSharp {
                }
 
                // Hack around System.Reflection as found everywhere else
-               public MemberInfo [] FindMembers (MemberTypes mt, BindingFlags bf, MemberFilter filter, object criteria)
+               public override MemberList FindMembers (MemberTypes mt, BindingFlags bf,
+                                                       MemberFilter filter, object criteria)
                {
                        ArrayList members = new ArrayList ();
 
@@ -259,26 +278,21 @@ namespace Mono.CSharp {
                        }
 
                        if (((bf & BindingFlags.DeclaredOnly) == 0) && (TypeBuilder.BaseType != null)) {
-                               MemberInfo [] parent_mi;
+                               MemberList parent_mi;
                                
                                parent_mi = TypeContainer.FindMembers (
                                        TypeBuilder.BaseType, mt, bf, filter, criteria);
 
-                               if (parent_mi != null)
-                                       members.AddRange (parent_mi);
+                               members.AddRange (parent_mi);
                        }
-                       
-                       // The rest of the cases, if any, are unhandled at present.
 
-                       int count = members.Count;
+                       return new MemberList (members);
+               }
 
-                       if (count > 0) {
-                               MemberInfo [] mi = new MemberInfo [count];
-                               members.CopyTo (mi, 0);
-                               return mi;
+               public override MemberCache MemberCache {
+                       get {
+                               return member_cache;
                        }
-
-                       return null;
                }
 
                //
@@ -298,6 +312,9 @@ namespace Mono.CSharp {
                        if (return_type.IsPointer && !UnsafeOK (this))
                                return;
 
+                       if (arg_types == null)
+                               return;
+
                        foreach (Type t in arg_types){
 
                                if (t == null)
@@ -349,6 +366,9 @@ namespace Mono.CSharp {
                        PropertyBuilder pb;
                        MethodBuilder get = null, set = null;
                        ip.Type = this.ResolveTypeExpr (ip.Type, false, ip.Location);
+                       if (ip.Type == null)
+                               return;
+                       
                        Type prop_type = ip.Type.Type;
                        Type [] setter_args = new Type [1];
 
@@ -378,7 +398,7 @@ namespace Mono.CSharp {
                                //
                                Type [] null_types = null;
                                InternalParameters inp = new InternalParameters
-                                       (null_types, Parameters.GetEmptyReadOnlyParameters ());
+                                       (null_types, Parameters.EmptyReadOnlyParameters);
                                
                                if (!RegisterMethod (get, inp, null)) {
                                        Error111 (ip);
@@ -434,6 +454,9 @@ namespace Mono.CSharp {
                        MyEventBuilder eb;
                        MethodBuilder add = null, remove = null;
                        ie.Type = this.ResolveTypeExpr (ie.Type, false, ie.Location);
+                       if (ie.Type == null)
+                               return;
+                       
                        Type event_type = ie.Type.Type;
 
                        if (event_type == null)
@@ -445,7 +468,7 @@ namespace Mono.CSharp {
                        Type [] parameters = new Type [1];
                        parameters [0] = event_type;
 
-                       eb = new MyEventBuilder (TypeBuilder, ie.Name,
+                       eb = new MyEventBuilder (null, TypeBuilder, ie.Name,
                                                 EventAttributes.None, event_type);
 
                        //
@@ -497,6 +520,9 @@ namespace Mono.CSharp {
                {
                        PropertyBuilder pb;
                        ii.Type = this.ResolveTypeExpr (ii.Type, false, ii.Location);
+                       if (ii.Type == null)
+                               return;
+                       
                        Type prop_type = ii.Type.Type;
                        Type [] arg_types = ii.ParameterTypes (this);
                        Type [] value_arg_types;
@@ -640,10 +666,13 @@ namespace Mono.CSharp {
 
                Type GetInterfaceTypeByName (string name)
                {
-                       Type t = FindType (name);
+                       Type t = FindType (Location, name);
 
-                       if (t == null)
+                       if (t == null) {
+                               Report.Error (246, Location, "The type or namespace `" + name +
+                                             "' could not be found");
                                return null;
+                       }
                        
                        if (t.IsInterface)
                                return t;
@@ -755,7 +784,7 @@ namespace Mono.CSharp {
 
                        TypeManager.AddUserInterface (Name, TypeBuilder, this, ifaces);
                        InTransit = false;
-                       
+
                        return TypeBuilder;
                }
 
@@ -796,7 +825,7 @@ namespace Mono.CSharp {
                /// <summary>
                ///   Performs semantic analysis, and then generates the IL interfaces
                /// </summary>
-               public override bool Define (TypeContainer parent)
+               public override bool DefineMembers (TypeContainer parent)
                {
                        if (!SemanticAnalysis ())
                                return false;
@@ -823,7 +852,28 @@ namespace Mono.CSharp {
                                if (cb != null)
                                        TypeBuilder.SetCustomAttribute (cb);
                        }
-                       
+
+#if CACHE
+                       if (TypeBuilder.BaseType != null)
+                               parent_container = TypeManager.LookupMemberContainer (TypeBuilder.BaseType);
+
+                       member_cache = new MemberCache (this);
+#endif
+                       members_defined = true;
+                       return true;
+               }
+
+               /// <summary>
+               ///   Applies all the attributes.
+               /// </summary>
+               public override bool Define (TypeContainer parent)
+               {
+                       if (OptAttributes != null) {
+                               EmitContext ec = new EmitContext (parent, this, Location, null, null,
+                                                                 ModFlags, false);
+                               Attribute.ApplyAttributes (ec, TypeBuilder, this, OptAttributes, Location);
+                       }
+
                        return true;
                }
 
@@ -860,6 +910,61 @@ namespace Mono.CSharp {
                        return cb;
                }
 
+               //
+               // IMemberContainer
+               //
+
+               string IMemberContainer.Name {
+                       get {
+                               return Name;
+                       }
+               }
+
+               Type IMemberContainer.Type {
+                       get {
+                               return TypeBuilder;
+                       }
+               }
+
+               IMemberContainer IMemberContainer.Parent {
+                       get {
+                               return parent_container;
+                       }
+               }
+
+               MemberCache IMemberContainer.MemberCache {
+                       get {
+                               return member_cache;
+                       }
+               }
+
+               bool IMemberContainer.IsInterface {
+                       get {
+                               return true;
+                       }
+               }
+
+               MemberList IMemberContainer.GetMembers (MemberTypes mt, BindingFlags bf)
+               {
+                       // Interfaces only contain instance members.
+                       if ((bf & BindingFlags.Instance) == 0)
+                               return MemberList.Empty;
+                       if ((bf & BindingFlags.Public) == 0)
+                               return MemberList.Empty;
+
+                       ArrayList members = new ArrayList ();
+
+                       if ((mt & MemberTypes.Method) != 0)
+                               members.AddRange (method_builders);
+
+                       if ((mt & MemberTypes.Property) != 0)
+                               members.AddRange (property_builders);
+
+                       if ((mt & MemberTypes.Event) != 0)
+                               members.AddRange (event_builders);
+
+                       return new MemberList (members);
+               }
        }
 
        public class InterfaceMemberBase {