📄 Core/ISymbolExtensions.cs
using System.Collections.Generic;
using Microsoft.CodeAnalysis;

namespace Reacher;

internal static class ISymbolExtensions
{
    public static HashSet<ISymbol> ExplicitOrImplicitInterfaceImplementations(this ISymbol member) =>
        [.. member.ExplicitInterfaceImplementations(), .. member.ImplicitInterfaceImplementations()];

    public static HashSet<ISymbol> ExplicitInterfaceImplementations(this ISymbol member) =>
        member switch
        {
            IMethodSymbol method => [.. method.ExplicitInterfaceImplementations],
            IPropertySymbol property => [.. property.ExplicitInterfaceImplementations],
            _ => [],
        };

    public static HashSet<ISymbol> ImplicitInterfaceImplementations(this ISymbol member)
    {
        var interfaceMembers = new HashSet<ISymbol>(SymbolEqualityComparer.Default);

        foreach (var interfaceType in member.ContainingType.AllInterfaces)
        {
            foreach (var interfaceMember in interfaceType.GetMembers())
            {
                var implementation = member.ContainingType.FindImplementationForInterfaceMember(interfaceMember);
                if (SymbolEqualityComparer.Default.Equals(member, implementation))
                {
                    interfaceMembers.Add(interfaceMember);
                }
            }
        }

        return interfaceMembers;
    }

    public static ISymbol? GetOverriddenMember(this ISymbol member) =>
        member switch
        {
            IMethodSymbol method => method.OverriddenMethod,
            IPropertySymbol property => property.OverriddenProperty,
            IEventSymbol @event => @event.OverriddenEvent,
            _ => null,
        };
}