//
// Author:
// Miguel de Icaza (miguel@gnu.org)
+// Anirban Bhattacharjee (banirban@novell.com)
//
// Licensed under the terms of the GNU GPL
//
using System.Reflection;
using System.Reflection.Emit;
-namespace Mono.CSharp {
+namespace Mono.MonoBASIC {
struct TypeAndMethods {
public Type type;
// because it was private, we could not use the match
//
public bool [] found;
+
+ // If a method is defined here, then we always need to
+ // create a proxy for it. This is used when implementing
+ // an interface's indexer with a different DefaultPropName.
+ public MethodInfo [] need_proxy;
}
public class PendingImplementation {
Type current_type = t;
do {
- MemberInfo [] mi;
+ MemberList mi;
mi = TypeContainer.FindMembers (
current_type, MemberTypes.Method,
searching = false;
}
- if (mi == null)
- continue;
-
- int count = mi.Length;
- if (count == 0)
+ if (mi.Count == 0)
continue;
- if (count == 1 && !(mi [0] is MethodBase))
+ if (mi.Count == 1 && !(mi [0] is MethodBase))
searching = false;
else
list = TypeManager.CopyNewMethods (list, mi);
if (ifaces != null){
foreach (Type t in ifaces){
MethodInfo [] mi;
-
- if (t is TypeBuilder){
+ /*if (t is TypeBuilder){
Interface iface;
iface = TypeManager.LookupInterface (t);
- mi = iface.GetMethods ();
- } else
- mi = t.GetMethods ();
+ mi = iface.GetMethods (container);
+ } else*/
+ mi = t.GetMethods ();
int count = mi.Length;
pending_implementations [i].type = t;
pending_implementations [i].methods = mi;
pending_implementations [i].args = new Type [count][];
pending_implementations [i].found = new bool [count];
+ pending_implementations [i].need_proxy = new MethodInfo [count];
int j = 0;
foreach (MethodInfo m in mi){
if (abstract_methods != null){
int count = abstract_methods.Count;
pending_implementations [i].methods = new MethodInfo [count];
+ pending_implementations [i].need_proxy = new MethodInfo [count];
abstract_methods.CopyTo (pending_implementations [i].methods, 0);
pending_implementations [i].found = new bool [count];
pending_implementations [i].args = new Type [count][];
- pending_implementations [i].type = type_builder;
+ pending_implementations [i].type = type_builder.BaseType;
int j = 0;
foreach (MemberInfo m in abstract_methods){
MethodInfo mi = (MethodInfo) m;
-
+
Type [] types = TypeManager.GetArgumentTypes (mi);
pending_implementations [i].args [j] = types;
// TypeBuilder.
//
ifaces = type_builder.GetInterfaces ();
+
#if DEBUG
{
Type x = type_builder;
}
}
#endif
-
- icount = ifaces.Length;
+
+ ifaces = TypeManager.ExpandInterfaces (ifaces);
+ icount = ifaces.Length;
//
// If we are implementing an abstract class, and we are not
// ourselves abstract, and there are abstract methods (C# allows
//
Lookup, ClearOne, ClearAll
}
-
+
/// <summary>
/// Whether the specified method is an interface method implementation
/// </summary>
- public MethodInfo IsInterfaceMethod (Type t, string name, Type ret_type, Type [] args)
+ public MethodInfo IsAbstractMethod (Type t, string name, Type ret_type, Type [] args)
{
- return InterfaceMethod (t, name, ret_type, args, Operation.Lookup);
+ return InterfaceMethod (t, name, ret_type, args, Operation.Lookup, null);
+ }
+
+ public MethodInfo IsAbstractIndexer (Type t, Type ret_type, Type [] args)
+ {
+ return InterfaceMethod (t, null, ret_type, args, Operation.Lookup, null);
}
public void ImplementMethod (Type t, string name, Type ret_type, Type [] args, bool clear_one)
{
- InterfaceMethod (t, name, ret_type, args, clear_one ? Operation.ClearOne : Operation.ClearAll);
+ InterfaceMethod (t, name, ret_type, args,
+ clear_one ? Operation.ClearOne : Operation.ClearAll, null);
+ }
+
+ public void ImplementIndexer (Type t, MethodInfo mi, Type ret_type, Type [] args, bool clear_one)
+ {
+ InterfaceMethod (t, mi.Name, ret_type, args,
+ clear_one ? Operation.ClearOne : Operation.ClearAll, mi);
}
/// <remarks>
/// arguments `args' implements an interface, this method will
/// return the MethodInfo that this method implements.
///
+ /// If `name' is null, we operate solely on the method's signature. This is for
+ /// instance used when implementing indexers.
+ ///
/// The `Operation op' controls whether to lookup, clear the pending bit, or clear
/// all the methods with the given signature.
+ ///
+ /// The `MethodInfo need_proxy' is used when we're implementing an interface's
+ /// indexer in a class. If the new indexer's DefaultPropName does not match the one
+ /// that was used in the interface, then we always need to create a proxy for it.
+ ///
/// </remarks>
- public MethodInfo InterfaceMethod (Type t, string name, Type ret_type, Type [] args, Operation op)
+ public MethodInfo InterfaceMethod (Type t, string name, Type ret_type, Type [] args,
+ Operation op, MethodInfo need_proxy)
{
int arg_len = args.Length;
continue;
}
- if (name != m.Name){
+ // `need_proxy' is not null when we're implementing an
+ // interface indexer and this is Clear(One/All) operation.
+ // If `name' is null, then we do a match solely based on the
+ // signature and not on the name (this is done in the Lookup
+ // for an interface indexer).
+ if ((name != null) && (need_proxy == null) && (name != m.Name)){
i++;
continue;
}
continue;
}
- if (op != Operation.Lookup)
- tm.methods [i] = null;
+ if (op != Operation.Lookup){
+ // If `t != null', then this is an explicitly interface
+ // implementation and we can always clear the method.
+ // `need_proxy' is not null if we're implementing an
+ // interface indexer. In this case, we need to create
+ // a proxy if the implementation's DefaultPropName doesn't
+ // match the DefaultPropName in the interface.
+ if ((t == null) && (need_proxy != null) && (name != m.Name))
+ tm.need_proxy [i] = need_proxy;
+ else
+ tm.methods [i] = null;
+ }
tm.found [i] = true;
//
container.TypeBuilder.DefineMethodOverride (proxy, iface_method);
}
+ static bool IsPropertyGetMethod (string m)
+ {
+ return (m.Substring (0, 4) == "get_");
+ }
+
+ static bool IsPropertySetMethod (string m)
+ {
+ return (m.Substring (0, 4) == "set_");
+ }
+
+ MethodInfo FindExplicitImplementation (string iface_name, string method_name)
+ {
+ if (container.Properties != null) {
+ foreach (Property p in container.Properties)
+ {
+ if (p.Implements != null) {
+ if (IsPropertyGetMethod (method_name) && (container.Namespace.Name + "." + p.Implements.ToString() == iface_name + "." + method_name.Substring(4)))
+ return p.PropertyBuilder.GetGetMethod(true);
+
+ if (IsPropertySetMethod (method_name) && (container.Namespace.Name + "." + p.Implements.ToString() == iface_name + "." + method_name.Substring(4)))
+ return p.PropertyBuilder.GetSetMethod(true);
+ }
+ }
+ }
+
+ if (container.Methods != null)
+ {
+ foreach (Method m in container.Methods)
+ {
+ if (m.Implements != null)
+ {
+ if (container.Namespace.Name + "." + m.Implements.ToString() == iface_name + "." + method_name)
+ return (MethodInfo) m.MethodBuilder;
+ }
+ }
+ }
+ return null;
+ }
+
/// <summary>
/// This function tells whether one of our parent classes implements
/// the given method (which turns out, it is valid to have an interface
bool ParentImplements (Type iface_type, MethodInfo mi)
{
MethodSignature ms;
+ MethodInfo mr;
Type [] args = TypeManager.GetArgumentTypes (mi);
+
ms = new MethodSignature (mi.Name, mi.ReturnType, args);
- MemberInfo [] list = TypeContainer.FindMembers (
+ MemberList list = TypeContainer.FindMembers (
container.TypeBuilder.BaseType, MemberTypes.Method | MemberTypes.Property,
BindingFlags.Public | BindingFlags.Instance,
MethodSignature.method_signature_filter, ms);
- if (list == null || list.Length == 0)
- return false;
-
- DefineProxy (iface_type, (MethodInfo) list [0], mi, args);
- return true;
+ if (list.Count == 0)
+ {
+ mr = FindExplicitImplementation (iface_type.ToString(), mi.Name);
+ if (mr == null)
+ return false;
+ }
+ else
+ mr = (MethodInfo) list[0];
+
+ DefineProxy (iface_type, mr, mi, args);
+ return true;
}
-
+
/// <summary>
/// Verifies that any pending abstract methods or interface methods
/// were implemented.
continue;
if (type.IsInterface){
+ MethodInfo need_proxy =
+ pending_implementations [i].need_proxy [j];
+
+ if (need_proxy != null) {
+ Type [] args = TypeManager.GetArgumentTypes (mi);
+ DefineProxy (type, need_proxy, mi, args);
+ continue;
+ }
+
if (ParentImplements (type, mi))
continue;
-
+
string extra = "";
if (pending_implementations [i].found [j])
type.FullName + "." + mi.Name + "'" + extra);
} else {
Report.Error (
- 534, container.Location,
+ 30610, container.Location,
"`" + container.Name + "' does not implement " +
- "inherited abstract member `" +
+ "inherited 'MustOverride' member `" +
type.FullName + "." + mi.Name + "'");
}
errors = true;