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

namespace Reacher.MemberCollectors;

internal class MembersCollector : SymbolVisitor
{
    public IReadOnlySet<ISymbol> Members => members;
    private readonly HashSet<ISymbol> members = new(SymbolEqualityComparer.Default);

    public override void VisitAssembly(IAssemblySymbol symbol)
    {
        symbol.GlobalNamespace.Accept(this);
    }

    public override void VisitNamespace(INamespaceSymbol symbol)
    {
        foreach (var namespaceOrType in symbol.GetMembers())
        {
            namespaceOrType.Accept(this);
        }
    }

    public override void VisitNamedType(INamedTypeSymbol type)
    {
        foreach (var member in type.GetMembers())
        {
            member.Accept(this);
        }

        foreach (var nestedType in type.GetTypeMembers())
        {
            nestedType.Accept(this);
        }
    }

    public override void VisitMethod(IMethodSymbol method) => VisitMember(method);

    public override void VisitProperty(IPropertySymbol property) => VisitMember(property);

    private void VisitMember(ISymbol member)
    {
        if (ShouldMemberBeIncluded(member))
        {
            members.Add(member);
        }
    }

    protected virtual bool ShouldMemberBeIncluded(ISymbol member) => true;
}