Better messages than a throw
[mono.git] / mcs / mcs / pending.cs
old mode 100755 (executable)
new mode 100644 (file)
index fb7a98f..98a4e99
@@ -23,7 +23,7 @@ namespace Mono.CSharp {
 
                // 
                // Whether it is optional, this is used to allow the explicit/implicit
-               // implementation when a parent class already implements an interface. 
+               // implementation when a base class already implements an interface. 
                //
                // For example:
                //
@@ -68,7 +68,7 @@ namespace Mono.CSharp {
 
                /// <summary>
                ///   This is the array of TypeAndMethods that describes the pending implementations
-               ///   (both interfaces and abstract methods in parent class)
+               ///   (both interfaces and abstract methods in base class)
                /// </summary>
                TypeAndMethods [] pending_implementations;
 
@@ -88,7 +88,7 @@ namespace Mono.CSharp {
 
                // <remarks>
                //   Returns a list of the abstract methods that are exposed by all of our
-               //   parents that we must implement.  Notice that this `flattens' the
+               //   bases that we must implement.  Notice that this `flattens' the
                //   method search space, and takes into account overrides.  
                // </remarks>
                static ArrayList GetAbstractMethods (Type t)
@@ -102,8 +102,8 @@ namespace Mono.CSharp {
                                
                                mi = TypeContainer.FindMembers (
                                        current_type, MemberTypes.Method,
-                                       BindingFlags.Public | BindingFlags.Instance |
-                                       BindingFlags.DeclaredOnly,
+                                       BindingFlags.Public | BindingFlags.NonPublic |
+                                       BindingFlags.Instance | BindingFlags.DeclaredOnly,
                                        virtual_method_filter, null);
 
                                if (current_type == TypeManager.object_type)
@@ -148,12 +148,15 @@ namespace Mono.CSharp {
                        foreach (MissingInterfacesInfo missing in missing_ifaces){
                                MethodInfo [] mi;
                                Type t = missing.Type;
-                               
+
+                               if (!t.IsInterface)
+                                       continue;
+
                                if (t is TypeBuilder){
-                                       Interface iface;
+                                       TypeContainer iface;
 
                                        iface = TypeManager.LookupInterface (t);
-                                       
+
                                        mi = iface.GetMethods ();
                                } else 
                                        mi = t.GetMethods ();
@@ -172,7 +175,13 @@ namespace Mono.CSharp {
                                
                                int j = 0;
                                foreach (MethodInfo m in mi){
-                                       Type [] types = TypeManager.GetArgumentTypes (m);
+                                       Type [] types;
+                                       
+                                       // If there is a previous error, just ignore
+                                       if (m == null)
+                                               types = TypeManager.NoTypes;
+                                       else
+                                               types = TypeManager.GetArgumentTypes (m);
                                        
                                        pending_implementations [i].args [j] = types;
                                        j++;
@@ -229,7 +238,7 @@ namespace Mono.CSharp {
                        //
                        // Completely broken.  So we do it ourselves!
                        //
-                       TypeExpr [] impl = TypeManager.GetExplicitInterfaces (type_builder);
+                       Type [] impl = TypeManager.GetExplicitInterfaces (type_builder);
 
                        if (impl == null || impl.Length == 0)
                                return EmptyMissingInterfacesInfo;
@@ -237,7 +246,7 @@ namespace Mono.CSharp {
                        MissingInterfacesInfo [] ret = new MissingInterfacesInfo [impl.Length];
 
                        for (int i = 0; i < impl.Length; i++)
-                               ret [i] = new MissingInterfacesInfo (impl [i].Type);
+                               ret [i] = new MissingInterfacesInfo (impl [i]);
                        
                        // we really should not get here because Object doesnt implement any
                        // interfaces. But it could implement something internal, so we have
@@ -245,11 +254,9 @@ namespace Mono.CSharp {
                        if (type_builder.BaseType == null)
                                return ret;
                        
-                       TypeExpr [] parent_impls = TypeManager.GetInterfaces (type_builder.BaseType);
+                       Type [] base_impls = TypeManager.GetInterfaces (type_builder.BaseType);
                        
-                       foreach (TypeExpr te in parent_impls) {
-                               Type t = te.Type;
-                               
+                       foreach (Type t in base_impls) {
                                for (int i = 0; i < ret.Length; i ++) {
                                        if (t == ret [i].Type) {
                                                ret [i].Optional = true;
@@ -449,7 +456,7 @@ namespace Mono.CSharp {
                ///   For that case, we create an explicit implementation function
                ///   I.M in Y.
                /// </summary>
-               void DefineProxy (Type iface, MethodInfo parent_method, MethodInfo iface_method,
+               void DefineProxy (Type iface, MethodInfo base_method, MethodInfo iface_method,
                                  Type [] args)
                {
                        MethodBuilder proxy;
@@ -462,36 +469,26 @@ namespace Mono.CSharp {
                                MethodAttributes.NewSlot |
                                MethodAttributes.Virtual,
                                CallingConventions.Standard | CallingConventions.HasThis,
-                               parent_method.ReturnType, args);
+                               base_method.ReturnType, args);
 
                        int top = args.Length;
                        ILGenerator ig = proxy.GetILGenerator ();
 
-                       ig.Emit (OpCodes.Ldarg_0);
-                       for (int i = 0; i < top; i++){
-                               switch (i){
-                               case 0:
-                                       ig.Emit (OpCodes.Ldarg_1); break;
-                               case 1:
-                                       ig.Emit (OpCodes.Ldarg_2); break;
-                               case 2:
-                                       ig.Emit (OpCodes.Ldarg_3); break;
-                               default:
-                                       ig.Emit (OpCodes.Ldarg, i - 1); break;
-                               }
-                       }
-                       ig.Emit (OpCodes.Call, parent_method);
+                       for (int i = 0; i <= top; i++)
+                               ParameterReference.EmitLdArg (ig, i);
+
+                       ig.Emit (OpCodes.Call, base_method);
                        ig.Emit (OpCodes.Ret);
 
                        container.TypeBuilder.DefineMethodOverride (proxy, iface_method);
                }
                
                /// <summary>
-               ///   This function tells whether one of our parent classes implements
+               ///   This function tells whether one of our base classes implements
                ///   the given method (which turns out, it is valid to have an interface
-               ///   implementation in a parent
+               ///   implementation in a base
                /// </summary>
-               bool ParentImplements (Type iface_type, MethodInfo mi)
+               bool BaseImplements (Type iface_type, MethodInfo mi)
                {
                        MethodSignature ms;
                        
@@ -505,9 +502,9 @@ namespace Mono.CSharp {
                        if (list.Count == 0)
                                return false;
 
-                       MethodInfo parent = (MethodInfo) list [0];
-                       if (!parent.IsAbstract)
-                               DefineProxy (iface_type, parent, mi, args);
+                       MethodInfo base_method = (MethodInfo) list [0];
+                       if (!base_method.IsAbstract)
+                               DefineProxy (iface_type, base_method, mi, args);
                        return true;
                }
 
@@ -524,7 +521,7 @@ namespace Mono.CSharp {
                        for (i = 0; i < top; i++){
                                Type type = pending_implementations [i].type;
                                int j = 0;
-                               
+
                                foreach (MethodInfo mi in pending_implementations [i].methods){
                                        if (mi == null)
                                                continue;
@@ -539,18 +536,28 @@ namespace Mono.CSharp {
                                                        continue;
                                                }
 
-                                               if (ParentImplements (type, mi))
+                                               if (BaseImplements (type, mi))
                                                        continue;
 
                                                if (pending_implementations [i].optional)
                                                        continue;
-                                               
+
+                                               Report.SymbolRelatedToPreviousError (mi);
                                                if (pending_implementations [i].found [j]) {
-                                                       string[] methodLabel = TypeManager.CSharpSignature (mi).Split ('.');
-                                                       Report.Error (536, container.Location, "'{0}' does not implement interface member '{1}'. '{2}.{3}' is either static, not public, or has the wrong return type",
-                                                               container.Name, TypeManager.CSharpSignature (mi), container.Name, methodLabel[methodLabel.Length - 1]);
+                                                       if (mi.IsSpecialName) {
+                                                               string name = TypeManager.CSharpName (mi.DeclaringType) + '.' + mi.Name.Substring (4);
+                                                               Report.Error (551, container.Location, "Explicit interface implementation '{0}.{1}' is missing accessor '{1}'",
+                                                                       container.Name, name);
+                                                       } else {
+                                                               string[] methodLabel = TypeManager.CSharpSignature (mi).Split ('.');
+                                                               Report.Error (536, container.Location,
+                                                                       "'{0}' does not implement interface member '{1}'. '{2}.{3}' " +
+                                                                       "is either static, not public, or has the wrong return type",
+                                                                       container.Name, TypeManager.CSharpSignature (mi),
+                                                                       container.Name, methodLabel[methodLabel.Length - 1]);
+                                                       }
                                                }
-                                               else { 
+                                               else {
                                                        Report.Error (535, container.Location, "'{0}' does not implement interface member '{1}'",
                                                                container.Name, TypeManager.CSharpSignature (mi));
                                                }