// // Checks our base implementation if any // protected override bool CheckBase (TypeContainer parent) { // Check whether arguments were correct. if (!DoDefineParameters (parent)) return false; if (IsExplicitImpl) return true; string report_name; MethodSignature ms, base_ms; if (this is Indexer) { string name, base_name; report_name = "this"; name = TypeManager.IndexerPropertyName (parent.TypeBuilder); ms = new MethodSignature (name, null, ParameterTypes); base_name = TypeManager.IndexerPropertyName (parent.TypeBuilder.BaseType); base_ms = new MethodSignature (base_name, null, ParameterTypes); } else { report_name = Name; ms = base_ms = new MethodSignature (Name, null, ParameterTypes); } // // Verify if the parent has a type with the same name, and then // check whether we have to create a new slot for it or not. // Type ptype = parent.TypeBuilder.BaseType; // ptype is only null for System.Object while compiling corlib. if (ptype == null) { if ((ModFlags & Modifiers.NEW) != 0) WarningNotHiding (parent); return true; } MemberList props_this; props_this = TypeContainer.FindMembers ( parent.TypeBuilder, MemberTypes.Property, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance | BindingFlags.DeclaredOnly, MethodSignature.method_signature_filter, ms); if (props_this.Count > 0) { Report.Error (111, Location, "Class `" + parent.Name + "' " + "already defines a member called `" + report_name + "' " + "with the same parameter types"); return false; } MemberList mi_props; mi_props = TypeContainer.FindMembers ( ptype, MemberTypes.Property, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static, MethodSignature.inheritable_method_signature_filter, base_ms); if (mi_props.Count > 0){ PropertyInfo parent_property = (PropertyInfo) mi_props [0]; string name = parent_property.DeclaringType.Name + "." + parent_property.Name; MethodInfo get, set, parent_method; get = parent_property.GetGetMethod (true); set = parent_property.GetSetMethod (true); if (get != null) parent_method = get; else if (set != null) parent_method = set; else throw new Exception ("Internal error!"); if (!CheckMethodAgainstBase (parent, flags, parent_method, name)) return false; if ((ModFlags & Modifiers.NEW) == 0) { Type parent_type = TypeManager.TypeToCoreType ( parent_property.PropertyType); if (parent_type != MemberType) { Report.Error ( 508, Location, parent.MakeName (Name) + ": cannot " + "change return type when overriding " + "inherited member " + name); return false; } } } else { if ((ModFlags & Modifiers.NEW) != 0) WarningNotHiding (parent); if ((ModFlags & Modifiers.OVERRIDE) != 0){ if (this is Indexer) Report.Error (115, Location, parent.MakeName (Name) + " no suitable indexers found to override"); else Report.Error (115, Location, parent.MakeName (Name) + " no suitable properties found to override"); return false; } } return true; }
// // Checks our base implementation if any // protected override bool CheckBase (TypeContainer parent) { // Check whether arguments were correct. if (!DoDefineParameters (parent)) return false; MethodSignature ms = new MethodSignature (Name, null, ParameterTypes); if (IsOperator) { flags |= MethodAttributes.SpecialName | MethodAttributes.HideBySig; } else { MemberList mi_this; mi_this = TypeContainer.FindMembers ( parent.TypeBuilder, MemberTypes.Method, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance | BindingFlags.DeclaredOnly, MethodSignature.method_signature_filter, ms); if (mi_this.Count > 0) { Report.Error (111, Location, "Class `" + parent.Name + "' " + "already defines a member called `" + Name + "' " + "with the same parameter types"); return false; } } // // Verify if the parent has a type with the same name, and then // check whether we have to create a new slot for it or not. // Type ptype = parent.TypeBuilder.BaseType; // ptype is only null for System.Object while compiling corlib. if (ptype != null){ MemberList mi, mi_static, mi_instance; mi_instance = TypeContainer.FindMembers ( ptype, MemberTypes.Method, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance, MethodSignature.inheritable_method_signature_filter, ms); if (mi_instance.Count > 0){ mi = mi_instance; } else { mi_static = TypeContainer.FindMembers ( ptype, MemberTypes.Method, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static, MethodSignature.inheritable_method_signature_filter, ms); if (mi_static.Count > 0) mi = mi_static; else mi = null; } if (mi != null && mi.Count > 0){ parent_method = (MethodInfo) mi [0]; string name = parent_method.DeclaringType.Name + "." + parent_method.Name; if (!CheckMethodAgainstBase (parent, flags, parent_method, name)) return false; if ((ModFlags & Modifiers.NEW) == 0) { Type parent_ret = TypeManager.TypeToCoreType ( parent_method.ReturnType); if (parent_ret != MemberType) { Report.Error ( 508, Location, parent.MakeName (Name) + ": cannot " + "change return type when overriding " + "inherited member " + name); return false; } } } else { if ((ModFlags & Modifiers.NEW) != 0) WarningNotHiding (parent); if ((ModFlags & Modifiers.OVERRIDE) != 0){ Report.Error (115, Location, parent.MakeName (Name) + " no suitable methods found to override"); } } } else if ((ModFlags & Modifiers.NEW) != 0) WarningNotHiding (parent); return true; }
private static MemberInfo [] FindMethodBase (Type type, BindingFlags binding_flags, MethodSignature signature) { MemberList ml = TypeManager.FindMembers ( type, MemberTypes.Constructor | MemberTypes.Method | MemberTypes.Property | MemberTypes.Custom, binding_flags, MethodSignature.method_signature_filter, signature); if (ml == null) return empty_member_infos; return FilterOverridenMembersOut ((MemberInfo []) ml); }
private static MemberInfo FindDocumentedMemberNoNest ( MemberCore mc, Type type, string member_name, Type [] param_list, DeclSpace ds, out int warning_type, string cref, bool warn419, string name_for_error, Report Report) { warning_type = 0; MemberInfo [] mis; if (param_list == null) { // search for fields/events etc. mis = TypeManager.MemberLookup (type, null, type, MemberTypes.All, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance, member_name, null); mis = FilterOverridenMembersOut (mis); if (mis == null || mis.Length == 0) return null; if (warn419 && IsAmbiguous (mis)) Report419 (mc, name_for_error, mis, Report); return mis [0]; } MethodSignature msig = new MethodSignature (member_name, null, param_list); mis = FindMethodBase (type, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance, msig); if (warn419 && mis.Length > 0) { if (IsAmbiguous (mis)) Report419 (mc, name_for_error, mis, Report); return mis [0]; } // search for operators (whose parameters exactly // matches with the list) and possibly report CS1581. string oper = null; string return_type_name = null; if (member_name.StartsWith ("implicit operator ")) { Operator.GetMetadataName (Operator.OpType.Implicit); return_type_name = member_name.Substring (18).Trim (wsChars); } else if (member_name.StartsWith ("explicit operator ")) { oper = Operator.GetMetadataName (Operator.OpType.Explicit); return_type_name = member_name.Substring (18).Trim (wsChars); } else if (member_name.StartsWith ("operator ")) { oper = member_name.Substring (9).Trim (wsChars); switch (oper) { // either unary or binary case "+": oper = param_list.Length == 2 ? Operator.GetMetadataName (Operator.OpType.Addition) : Operator.GetMetadataName (Operator.OpType.UnaryPlus); break; case "-": oper = param_list.Length == 2 ? Operator.GetMetadataName (Operator.OpType.Subtraction) : Operator.GetMetadataName (Operator.OpType.UnaryNegation); break; default: oper = Operator.GetMetadataName (oper); if (oper != null) break; warning_type = 1584; Report.Warning (1020, 1, mc.Location, "Overloadable {0} operator is expected", param_list.Length == 2 ? "binary" : "unary"); Report.Warning (1584, 1, mc.Location, "XML comment on `{0}' has syntactically incorrect cref attribute `{1}'", mc.GetSignatureForError (), cref); return null; } } // here we still don't consider return type (to // detect CS1581 or CS1002+CS1584). msig = new MethodSignature (oper, null, param_list); mis = FindMethodBase (type, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance, msig); if (mis.Length == 0) return null; // CS1574 MemberInfo mi = mis [0]; Type expected = mi is MethodInfo ? ((MethodInfo) mi).ReturnType : mi is PropertyInfo ? ((PropertyInfo) mi).PropertyType : null; if (return_type_name != null) { Type returnType = FindDocumentedType (mc, return_type_name, ds, cref, Report); if (returnType == null || returnType != expected) { warning_type = 1581; Report.Warning (1581, 1, mc.Location, "Invalid return type in XML comment cref attribute `{0}'", cref); return null; } } return mis [0]; }
/// <summary> /// 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 base /// </summary> bool BaseImplements (Type iface_type, MethodInfo mi, out MethodInfo base_method) { MethodSignature ms; AParametersCollection param = TypeManager.GetParameterData (mi); ms = new MethodSignature (mi.Name, TypeManager.TypeToCoreType (mi.ReturnType), param.Types); MemberList list = TypeContainer.FindMembers ( container.TypeBuilder.BaseType, MemberTypes.Method | MemberTypes.Property, BindingFlags.Public | BindingFlags.Instance, MethodSignature.method_signature_filter, ms); if (list.Count == 0) { base_method = null; return false; } if (TypeManager.ImplementsInterface (container.TypeBuilder.BaseType, iface_type)) { base_method = null; return true; } base_method = (MethodInfo) list [0]; if (base_method.DeclaringType.IsInterface) return false; if (!base_method.IsPublic) return false; if (!base_method.IsAbstract && !base_method.IsVirtual) // FIXME: We can avoid creating a proxy if base_method can be marked 'final virtual' instead. // However, it's too late now, the MethodBuilder has already been created (see bug 377519) DefineProxy (iface_type, base_method, mi, param); return true; }