Core/ExcludingMembersCollector.cs
+4
-2
diff --git a/Core/ExcludingMembersCollector.cs b/Core/ExcludingMembersCollector.cs
index 92961fc..788fc8f 100644
@@ -1,9 +1,11 @@
using System;
using System.Collections.Generic;
using Microsoft.CodeAnalysis;
namespace Reacher;
internal class ExcludingMembersCollector(IReadOnlySet<ISymbol> excludedMembers) : SymbolVisitor
internal class ExcludingMembersCollector(IReadOnlySet<ISymbol> excludedMembers, Predicate<ISymbol> predicate)
: SymbolVisitor
{
public IReadOnlySet<ISymbol> Members => members;
private readonly HashSet<ISymbol> members = [];
@@ -40,7 +42,7 @@ internal class ExcludingMembersCollector(IReadOnlySet<ISymbol> excludedMembers)
private void VisitMember(ISymbol member)
{
if (excludedMembers.Contains(member))
if (excludedMembers.Contains(member) || !predicate(member))
{
return;
}
Core/ReachabilityAnalyzer.cs
+16
-4
diff --git a/Core/ReachabilityAnalyzer.cs b/Core/ReachabilityAnalyzer.cs
index be627a7..f42924f 100644
@@ -15,7 +15,11 @@ internal sealed class ReachabilityAnalyzer(IReadOnlyCollection<Compilation> comp
public void Analyze(ISymbol member, CancellationToken cancellationToken)
{
if (!TryGetAssociatedCompilation(member, out var compilation) || !reachableMembers.Add(member))
if (
!IsUserDefined(member)
|| !TryGetAssociatedCompilation(member, out var compilation)
|| !reachableMembers.Add(member)
)
{
return;
}
@@ -26,6 +30,9 @@ internal sealed class ReachabilityAnalyzer(IReadOnlyCollection<Compilation> comp
}
}
private static bool IsUserDefined(ISymbol member) =>
!member.IsImplicitlyDeclared && (member.CanBeReferencedByName || member.Name is "<Main>$");
private bool TryGetAssociatedCompilation(ISymbol member, [NotNullWhen(true)] out Compilation? compilation)
{
compilation = compilations.FirstOrDefault(c =>
@@ -41,11 +48,16 @@ internal sealed class ReachabilityAnalyzer(IReadOnlyCollection<Compilation> comp
)
{
var originalNode = declaration.GetSyntax(cancellationToken);
var identifiers = originalNode.DescendantNodes(ShouldDescendInto(originalNode)).OfType<IdentifierNameSyntax>();
var expressions = originalNode
.DescendantNodes(ShouldDescendInto(originalNode))
.OfType<ExpressionSyntax>()
.Where(e =>
e is IdentifierNameSyntax or ImplicitObjectCreationExpressionSyntax or ObjectCreationExpressionSyntax
);
var semanticModel = compilation.GetSemanticModel(declaration.SyntaxTree);
foreach (var identifier in identifiers)
foreach (var identifier in expressions)
{
if (!semanticModel.IsReachable(identifier))
{
@@ -75,7 +87,7 @@ internal sealed class ReachabilityAnalyzer(IReadOnlyCollection<Compilation> comp
private IReadOnlySet<ISymbol> GetUnreachableMembers()
{
var collector = new ExcludingMembersCollector(reachableMembers);
var collector = new ExcludingMembersCollector(reachableMembers, IsUserDefined);
foreach (var compilation in compilations)
{