X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mcs%2Fmcs%2Finterface.cs;h=2c5b939f41e93f6902ef39ac9182bc7e6281993e;hb=f282c09a4f474c0994bf739e0b300043fd342b80;hp=500317eb9dabb11f1ef9a63e69984489878a0c4b;hpb=6640d43fccd9b64ec6918390446330053ae31067;p=mono.git diff --git a/mcs/mcs/interface.cs b/mcs/mcs/interface.cs index 500317eb9da..2c5b939f41e 100755 --- a/mcs/mcs/interface.cs +++ b/mcs/mcs/interface.cs @@ -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 { /// /// Interfaces /// - public class Interface : DeclSpace { + public class Interface : DeclSpace, IMemberContainer { const MethodAttributes interface_method_attributes = MethodAttributes.Public | MethodAttributes.Abstract | @@ -44,9 +44,17 @@ namespace Mono.CSharp { ArrayList method_builders; ArrayList property_builders; + ArrayList event_builders; Attributes OptAttributes; + public string IndexerName; + + IMemberContainer parent_container; + MemberCache member_cache; + + bool members_defined; + // These will happen after the semantic analysis // Hashtable defined_indexers; @@ -71,6 +79,7 @@ namespace Mono.CSharp { method_builders = new ArrayList (); property_builders = new ArrayList (); + event_builders = new ArrayList (); } public AdditionResult AddMethod (InterfaceMethod imethod) @@ -221,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); @@ -232,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 (); @@ -248,35 +271,36 @@ namespace Mono.CSharp { members.Add (pb); } - if ((bf & BindingFlags.DeclaredOnly) == 0){ - MemberInfo [] parent_mi; + if ((mt & MemberTypes.Event) != 0) { + foreach (MyEventBuilder eb in event_builders) + if (filter (eb, criteria)) + members.Add (eb); + } + + if (((bf & BindingFlags.DeclaredOnly) == 0) && (TypeBuilder.BaseType != null)) { + 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; } // // Populates the methods in the interface // - void PopulateMethod (InterfaceMethod im) + void PopulateMethod (TypeContainer parent, DeclSpace decl_space, InterfaceMethod im) { - Type return_type = RootContext.LookupType (this, im.ReturnType, false, im.Location); + Type return_type = this.ResolveType (im.ReturnType, false, im.Location); Type [] arg_types = im.ParameterTypes (this); MethodBuilder mb; Parameter [] p; @@ -288,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) @@ -323,16 +350,26 @@ namespace Mono.CSharp { if (i != arg_types.Length) Console.WriteLine ("Implement the type definition for params"); } + + EmitContext ec = new EmitContext (parent, decl_space, Location, null, + return_type, ModFlags, false); + + if (im.OptAttributes != null) + Attribute.ApplyAttributes (ec, mb, im, im.OptAttributes, Location); } // // Populates the properties in the interface // - void PopulateProperty (InterfaceProperty ip) + void PopulateProperty (TypeContainer parent, DeclSpace decl_space, InterfaceProperty ip) { PropertyBuilder pb; MethodBuilder get = null, set = null; - Type prop_type = RootContext.LookupType (this, ip.Type, false, ip.Location); + 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]; if (prop_type == null) @@ -361,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); @@ -395,6 +432,12 @@ namespace Mono.CSharp { } } + EmitContext ec = new EmitContext (parent, decl_space, Location, null, + null, ModFlags, false); + + if (ip.OptAttributes != null) + Attribute.ApplyAttributes (ec, pb, ip, ip.OptAttributes, Location); + TypeManager.RegisterProperty (pb, get, set); property_builders.Add (pb); } @@ -402,21 +445,85 @@ namespace Mono.CSharp { // // Populates the events in the interface // - void PopulateEvent (InterfaceEvent ie) + void PopulateEvent (TypeContainer parent, DeclSpace decl_space, InterfaceEvent ie) { // // FIXME: We need to do this after delegates have been // declared or we declare them recursively. // + 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) + return; + + if (event_type.IsPointer && !UnsafeOK (this)) + return; + + Type [] parameters = new Type [1]; + parameters [0] = event_type; + + eb = new MyEventBuilder (null, TypeBuilder, ie.Name, + EventAttributes.None, event_type); + + // + // Now define the accessors + // + string add_name = "add_" + ie.Name; + + add = TypeBuilder.DefineMethod ( + add_name, property_attributes, null, parameters); + add.DefineParameter (1, ParameterAttributes.None, "value"); + eb.SetAddOnMethod (add); + + string remove_name = "remove_" + ie.Name; + remove = TypeBuilder.DefineMethod ( + remove_name, property_attributes, null, parameters); + remove.DefineParameter (1, ParameterAttributes.None, "value"); + eb.SetRemoveOnMethod (remove); + + Parameter [] parms = new Parameter [1]; + parms [0] = new Parameter (ie.Type, "value", Parameter.Modifier.NONE, null); + InternalParameters ip = new InternalParameters ( + this, new Parameters (parms, null, Location.Null)); + + if (!RegisterMethod (add, ip, parameters)) { + Error111 (ie); + return; + } + + if (!RegisterMethod (remove, ip, parameters)) { + Error111 (ie); + return; + } + + EmitContext ec = new EmitContext (parent, decl_space, Location, null, + null, ModFlags, false); + + + if (ie.OptAttributes != null) + Attribute.ApplyAttributes (ec, eb, ie, ie.OptAttributes, Location); + + TypeManager.RegisterEvent (eb, add, remove); + event_builders.Add (eb); } // // Populates the indexers in the interface // - void PopulateIndexer (InterfaceIndexer ii) + void PopulateIndexer (TypeContainer parent, DeclSpace decl_space, InterfaceIndexer ii) { PropertyBuilder pb; - Type prop_type = RootContext.LookupType (this, ii.Type, false, ii.Location); + 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; @@ -446,8 +553,15 @@ namespace Mono.CSharp { value_arg_types [1] = prop_type; } + EmitContext ec = new EmitContext (parent, decl_space, Location, null, + null, ModFlags, false); + + IndexerName = Attribute.ScanForIndexerName (ec, ii.OptAttributes); + if (IndexerName == null) + IndexerName = "Item"; + pb = TypeBuilder.DefineProperty ( - "Item", PropertyAttributes.None, + IndexerName, PropertyAttributes.None, prop_type, arg_types); MethodBuilder set_item = null, get_item = null; @@ -455,7 +569,8 @@ namespace Mono.CSharp { Parameter [] p = ii.Parameters.FixedParameters; get_item = TypeBuilder.DefineMethod ( - "get_Item", property_attributes, prop_type, arg_types); + "get_" + IndexerName, property_attributes, + prop_type, arg_types); pb.SetGetMethod (get_item); // // HACK because System.Reflection.Emit is lame @@ -478,17 +593,24 @@ namespace Mono.CSharp { if (ii.HasSet){ Parameter [] p = ii.Parameters.FixedParameters; + Parameter [] pv; int i = 0; + pv = new Parameter [p.Length + 1]; + p.CopyTo (pv, 0); + pv [p.Length] = new Parameter (ii.Type, "value", Parameter.Modifier.NONE, null); + Parameters value_params = new Parameters (pv, null, Location.Null); + value_params.GetParameterInfo (decl_space); + set_item = TypeBuilder.DefineMethod ( - "set_Item", property_attributes, + "set_" + IndexerName, property_attributes, TypeManager.void_type, value_arg_types); pb.SetSetMethod (set_item); // // HACK because System.Reflection.Emit is lame // InternalParameters ip = new InternalParameters ( - value_arg_types, ii.Parameters); + value_arg_types, value_params); if (!RegisterMethod (set_item, ip, value_arg_types)) { Error111 (ii); return; @@ -503,7 +625,10 @@ namespace Mono.CSharp { set_item.DefineParameter (i + 1, ParameterAttributes.None, "value"); } - TypeManager.RegisterProperty (pb, get_item, set_item); + + if (ii.OptAttributes != null) + Attribute.ApplyAttributes (ec, pb, ii, ii.OptAttributes, Location); + property_builders.Add (pb); } @@ -541,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; @@ -590,11 +718,18 @@ namespace Mono.CSharp { error = true; return null; } - + + if (!Parent.AsAccessible (t, ModFlags)) + Report.Error (61, Location, + "Inconsistent accessibility: base interface `" + + TypeManager.CSharpName (t) + "' is less " + + "accessible than interface `" + + Name + "'"); + tbases [i++] = t; } - return tbases; + return TypeManager.ExpandInterfaces (tbases); } // @@ -649,45 +784,96 @@ namespace Mono.CSharp { TypeManager.AddUserInterface (Name, TypeBuilder, this, ifaces); InTransit = false; - + return TypeBuilder; } + + // + // Defines the indexers, and also verifies that the IndexerNameAttribute in the + // interface is consistent. Either it is `Item' or it is the name defined by all the + // indexers with the `IndexerName' attribute. + // + // Turns out that the IndexerNameAttribute is applied to each indexer, + // but it is never emitted, instead a DefaultName attribute is attached + // to the interface + // + void DefineIndexers (TypeContainer parent) + { + string interface_indexer_name = null; + + foreach (InterfaceIndexer ii in defined_indexer){ + + PopulateIndexer (parent, this, ii); + + if (interface_indexer_name == null){ + interface_indexer_name = IndexerName; + continue; + } + + if (IndexerName == interface_indexer_name) + continue; + + Report.Error ( + 668, "Two indexers have different names, " + + " you should use the same name for all your indexers"); + } + if (interface_indexer_name == null) + interface_indexer_name = "Item"; + IndexerName = interface_indexer_name; + } /// /// Performs semantic analysis, and then generates the IL interfaces /// - public override bool Define (TypeContainer parent) + public override bool DefineMembers (TypeContainer parent) { if (!SemanticAnalysis ()) return false; if (defined_method != null){ foreach (InterfaceMethod im in defined_method) - PopulateMethod (im); + PopulateMethod (parent, this, im); } if (defined_properties != null){ foreach (InterfaceProperty ip in defined_properties) - PopulateProperty (ip); + PopulateProperty (parent, this, ip); } if (defined_events != null) foreach (InterfaceEvent ie in defined_events) - PopulateEvent (ie); + PopulateEvent (parent, this, ie); - // - // FIXME: Pull the right indexer name out of the `IndexerName' attribute - // if (defined_indexer != null) { - foreach (InterfaceIndexer ii in defined_indexer) - PopulateIndexer (ii); + DefineIndexers (parent); CustomAttributeBuilder cb = EmitDefaultMemberAttr ( - parent, "Item", ModFlags, Location); + parent, IndexerName, ModFlags, Location); 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; + } + + /// + /// Applies all the attributes. + /// + 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; } @@ -724,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 { @@ -742,11 +983,10 @@ namespace Mono.CSharp { public class InterfaceProperty : InterfaceMemberBase { public readonly bool HasSet; public readonly bool HasGet; - public readonly string Type; - public readonly string type; public readonly Location Location; + public Expression Type; - public InterfaceProperty (string type, string name, + public InterfaceProperty (Expression type, string name, bool is_new, bool has_get, bool has_set, Attributes attrs, Location loc) : base (name, is_new, attrs) @@ -759,21 +999,24 @@ namespace Mono.CSharp { } public class InterfaceEvent : InterfaceMemberBase { - public readonly string Type; + public readonly Location Location; + public Expression Type; - public InterfaceEvent (string type, string name, bool is_new, Attributes attrs) + public InterfaceEvent (Expression type, string name, bool is_new, Attributes attrs, + Location loc) : base (name, is_new, attrs) { Type = type; + Location = loc; } } public class InterfaceMethod : InterfaceMemberBase { - public readonly string ReturnType; + public readonly Expression ReturnType; public readonly Parameters Parameters; public readonly Location Location; - public InterfaceMethod (string return_type, string name, bool is_new, Parameters args, + public InterfaceMethod (Expression return_type, string name, bool is_new, Parameters args, Attributes attrs, Location l) : base (name, is_new, attrs) { @@ -787,7 +1030,7 @@ namespace Mono.CSharp { /// public string GetSignature (DeclSpace ds) { - Type ret = RootContext.LookupType (ds, ReturnType, false, Location); + Type ret = ds.ResolveType (ReturnType, false, Location); string args = Parameters.GetSignature (ds); if ((ret == null) || (args == null)) @@ -805,10 +1048,10 @@ namespace Mono.CSharp { public class InterfaceIndexer : InterfaceMemberBase { public readonly bool HasGet, HasSet; public readonly Parameters Parameters; - public readonly string Type; public readonly Location Location; + public Expression Type; - public InterfaceIndexer (string type, Parameters args, bool do_get, bool do_set, + public InterfaceIndexer (Expression type, Parameters args, bool do_get, bool do_set, bool is_new, Attributes attrs, Location loc) : base ("", is_new, attrs) {