private static MemberDataBase FindEquivalentMemberInClassHierarchy(MemberDataBase oldMember, DeclaringTypeData newType, AssemblyFamily newAssemblyFamily)
        {
            var allowMatchOnNameOnly = true;
            var current = newType;

            while (current != null)
            {
                var newMember = MetadataComparer.FindEquivalentMember(oldMember, current, newAssemblyFamily, allowMatchOnNameOnly);
                if (newMember != null)
                {
                    return(newMember);
                }

                current = current.BaseType;
                allowMatchOnNameOnly = false;
            }

            return(null);
        }
        private static List <BreakingChangeBase> CompareTypes(TypeData oldTypeBase, TypeData newTypeBase, AssemblyFamily newAssemblyFamily)
        {
            var oldType = (TypeDefinitionData)oldTypeBase;
            var newType = (TypeDefinitionData)newTypeBase;

            var breakingChanges = MetadataComparer.CompareItems(oldType, newType, newAssemblyFamily);

            if (oldType.GenericParameters.Count == newType.GenericParameters.Count)
            {
                for (int i = 0; i < oldType.GenericParameters.Count; i++)
                {
                    breakingChanges.AddRange(MetadataComparer.CompareGenericTypeParameters(oldType.GenericParameters[i], newType.GenericParameters[i], newAssemblyFamily));
                }
            }

            var hasExternallyVisibleConstructor = oldType.GetMembers(".ctor").Count != 0;

            if (oldType.TypeKind != TypeKind.Delegate)
            {
                foreach (var oldMember in oldType.GetMembers())
                {
                    MemberDataBase newMember;
                    if (oldType.TypeKind == TypeKind.Class && oldMember.IsOverride == false)
                    {
                        newMember = MetadataComparer.FindEquivalentMemberInClassHierarchy(oldMember, newType, newAssemblyFamily);
                    }
                    else
                    {
                        newMember = MetadataComparer.FindEquivalentMember(oldMember, newType, newAssemblyFamily);
                    }

                    if (newMember != null)
                    {
                        breakingChanges.AddRange(MetadataComparer.CompareMembers(oldMember, newMember, newAssemblyFamily));
                        continue;
                    }

                    if (MetadataComparer.IsMemberKindChangeAllowed(oldMember, newType, newAssemblyFamily))
                    {
                        continue;
                    }

                    if (oldMember.IsOverride)
                    {
                        if (hasExternallyVisibleConstructor)
                        {
                            var baseMember = oldMember.GetBaseMember();
                            if (baseMember.IsAbstract)
                            {
                                breakingChanges.Add(new RemovedOverrideOfAbstractMember(oldMember, newType));
                            }
                        }

                        continue;
                    }

                    breakingChanges.Add(new RemovedMember(oldMember, newType));
                }
            }

            switch (oldType.TypeKind)
            {
            case TypeKind.Class:
                foreach (var newMember in newType.GetMembers())
                {
                    if (newMember.IsAbstract)
                    {
                        var oldMember = MetadataComparer.FindEquivalentMemberInClassHierarchy(newMember, oldType, newAssemblyFamily);
                        if (oldMember == null)
                        {
                            breakingChanges.Add(new AddedAbstractMember(newMember));
                        }
                    }
                    else if (newType.IsSealed == false && newMember.IsSealed && newMember.IsOverride)
                    {
                        // If the class contains a sealed override member, find the original equivalent member and see if derived
                        // classes would have been able to override the member previously.
                        var oldMember = MetadataComparer.FindEquivalentMemberInClassHierarchy(newMember, oldType, newAssemblyFamily);
                        if (oldMember != null && oldMember.CanBeOverridden)
                        {
                            breakingChanges.Add(new SealedMember(oldMember, newMember));
                        }
                    }
                }
                break;

            case TypeKind.Interface:
                foreach (var newMember in newType.GetMembers())
                {
                    var oldMember = MetadataComparer.FindEquivalentMember(newMember, oldType, newAssemblyFamily);
                    if (oldMember == null)
                    {
                        breakingChanges.Add(new AddedInterfaceMember(newMember));
                    }
                }
                break;

            case TypeKind.Delegate:
                MetadataComparer.CompareParameters(oldType, newType, newAssemblyFamily, breakingChanges);
                break;
            }
            return(breakingChanges);
        }