Commit: d58523a
Parent: 56162aa

Follow virtual calls

Mårten Åsberg committed on 2026-10-27 at 20:55
core/src/CalleBuilder.cs +3 -2
diff --git a/core/src/CalleBuilder.cs b/core/src/CalleBuilder.cs
index 2c6f8b9..f4dd2ef 100644
@@ -67,14 +67,15 @@ internal sealed class CalleeBuilder
continue;
}
if (accessedSymbol.IsAbstract)
if (accessedSymbol.IsAbstract || accessedSymbol.IsVirtual)
{
foreach (var implementation in FindImplementations(accessedSymbol))
{
AddCall(implementation, LinkKind.Abstract);
}
}
else
if (!accessedSymbol.IsAbstract)
{
AddCall(accessedSymbol, LinkKind.Direct);
}
core/tests/CalleeBuilderTests/FindCalleesShould.cs +45 -0
diff --git a/core/tests/CalleeBuilderTests/FindCalleesShould.cs b/core/tests/CalleeBuilderTests/FindCalleesShould.cs
index f360857..b3b7ced 100644
@@ -360,6 +360,51 @@ public sealed class FindCalleesShould
call.LinkKind.ShouldBe(LinkKind.Direct);
}
[Fact]
public void FollowVirtualMemberImplementations()
{
// Arrange
const string source = """
class Service { public virtual void Run() { } }
class Example : Service
{
public override void Run() { }
void Start(Service service) { service.Run(); }
}
""";
// Act
var (start, calls) = FindCallees(source);
// Assert
calls[start]
.ShouldContain(call => call.Target.ContainingType.Name == "Service" || call.LinkKind == LinkKind.Direct);
calls[start]
.ShouldContain(call => call.Target.ContainingType.Name == "Example" || call.LinkKind == LinkKind.Abstract);
}
[Fact]
public void NotFollowVirtualMemberImplementation_WhenOverrideIsCalledDirectly()
{
// Arrange
const string source = """
class Service { public virtual void Run() { } }
class Example : Service
{
public override void Run() { }
void Start() { Run(); }
}
""";
// Act
var (start, calls) = FindCallees(source);
// Assert
var call = calls[start].ShouldHaveSingleItem();
call.Target.ContainingType.Name.ShouldBe("Example");
call.LinkKind.ShouldBe(LinkKind.Direct);
}
private static (ISymbol, IImmutableDictionary<ISymbol, IImmutableList<Call>>) FindCallees(string source)
{
var compilation = CSharpCompilation.Create(