void RemoveInterfaceMembersHiddenByClassMembers(List <LookupGroup> lookupGroups) { foreach (var classLookupGroup in lookupGroups) { if (IsInterfaceOrSystemObject(classLookupGroup.DeclaringType)) { continue; } // The current lookup groups contains class members that might hide interface members bool hasNestedTypes = classLookupGroup.NestedTypes != null && classLookupGroup.NestedTypes.Count > 0; if (hasNestedTypes || !classLookupGroup.NonMethodIsHidden) { // Hide all members from interface types foreach (var interfaceLookupGroup in lookupGroups) { if (IsInterfaceOrSystemObject(interfaceLookupGroup.DeclaringType)) { interfaceLookupGroup.NestedTypes = null; interfaceLookupGroup.NonMethodIsHidden = true; interfaceLookupGroup.MethodsAreHidden = true; } } } else if (!classLookupGroup.MethodsAreHidden) { foreach (IMethod classMethod in classLookupGroup.Methods) { // Hide all non-methods from interface types, and all methods with the same signature // as a method in this class type. foreach (var interfaceLookupGroup in lookupGroups) { if (IsInterfaceOrSystemObject(interfaceLookupGroup.DeclaringType)) { interfaceLookupGroup.NestedTypes = null; interfaceLookupGroup.NonMethodIsHidden = true; if (interfaceLookupGroup.Methods != null && !interfaceLookupGroup.MethodsAreHidden) { // The mapping of virtual to overridden methods is already done, // so we can simply remove the methods from the collection interfaceLookupGroup.Methods.RemoveAll( m => ParameterListComparer.Compare(context, classMethod, m)); } } } } } } }
/// <summary> /// Adds members to 'newMethods'/'newNonMethod'. /// Removes any members in the existing lookup groups that were hidden by added members. /// Substitutes 'virtual' members in the existing lookup groups for added 'override' members. /// </summary> /// <param name="type">Declaring type of the members</param> /// <param name="members">List of members to add.</param> /// <param name="lookupGroups">List of existing lookup groups</param> /// <param name="treatAllParameterizedMembersAsMethods">Whether to treat properties as methods</param> /// <param name="typeBaseTypes">The base types of 'type' (initialized on demand)</param> /// <param name="newMethods">The target list for methods (created on demand).</param> /// <param name="newNonMethod">The target variable for non-method members.</param> void AddMembers(IType type, IEnumerable <IMember> members, List <LookupGroup> lookupGroups, bool treatAllParameterizedMembersAsMethods, ref IEnumerable <IType> typeBaseTypes, ref List <IParameterizedMember> newMethods, ref IMember newNonMethod) { foreach (IMember member in members) { IParameterizedMember method; if (treatAllParameterizedMembersAsMethods) { method = member as IParameterizedMember; } else { method = member as IMethod; } bool replacedVirtualMemberWithOverride = false; if (member.IsOverride) { // Replacing virtual member with override: // Go backwards so that we find the corresponding virtual member // in the most-derived type for (int i = lookupGroups.Count - 1; i >= 0 && !replacedVirtualMemberWithOverride; i--) { if (typeBaseTypes == null) { typeBaseTypes = type.GetNonInterfaceBaseTypes(context); } var lookupGroup = lookupGroups[i]; if (typeBaseTypes.Contains(lookupGroup.DeclaringType)) { if (method != null) { // Find the matching method, and replace it with the override for (int j = 0; j < lookupGroup.Methods.Count; j++) { if (ParameterListComparer.Compare(context, method, lookupGroup.Methods[j])) { lookupGroup.Methods[j] = method; replacedVirtualMemberWithOverride = true; break; } } } else { // If the member type matches, replace it with the override if (lookupGroup.NonMethod != null && lookupGroup.NonMethod.EntityType == member.EntityType) { lookupGroup.NonMethod = member; replacedVirtualMemberWithOverride = true; break; } } } } } // If the member wasn't an override, or if we didn't find any matching virtual method, // proceed to add the member. if (!replacedVirtualMemberWithOverride) { // Make the member hide other members: foreach (var lookupGroup in lookupGroups) { if (lookupGroup.AllHidden) { continue; // everything is already hidden } if (typeBaseTypes == null) { typeBaseTypes = type.GetNonInterfaceBaseTypes(context); } if (typeBaseTypes.Contains(lookupGroup.DeclaringType)) { // Methods hide all non-methods; Non-methods hide everything lookupGroup.NestedTypes = null; lookupGroup.NonMethodIsHidden = true; if (method == null) // !(member is IMethod) { lookupGroup.MethodsAreHidden = true; } } } // Add the new member if (method != null) { if (newMethods == null) { newMethods = new List <IParameterizedMember>(); } newMethods.Add(method); } else { newNonMethod = member; } } } }