diff --git a/gitnexus/test/fixtures/lang-resolution/csharp-collection-accessor/CollectionAccessor.csproj b/gitnexus/test/fixtures/lang-resolution/csharp-collection-accessor/CollectionAccessor.csproj
new file mode 100644
index 000000000..ec2cce143
--- /dev/null
+++ b/gitnexus/test/fixtures/lang-resolution/csharp-collection-accessor/CollectionAccessor.csproj
@@ -0,0 +1,5 @@
+
+
+ net8.0
+
+
diff --git a/gitnexus/test/fixtures/lang-resolution/csharp-collection-accessor/Models/Widget.cs b/gitnexus/test/fixtures/lang-resolution/csharp-collection-accessor/Models/Widget.cs
new file mode 100644
index 000000000..fda3acc87
--- /dev/null
+++ b/gitnexus/test/fixtures/lang-resolution/csharp-collection-accessor/Models/Widget.cs
@@ -0,0 +1,8 @@
+namespace Models;
+
+public class Widget
+{
+ public void Render()
+ {
+ }
+}
diff --git a/gitnexus/test/fixtures/lang-resolution/csharp-collection-accessor/Services/Renderer.cs b/gitnexus/test/fixtures/lang-resolution/csharp-collection-accessor/Services/Renderer.cs
new file mode 100644
index 000000000..6197b611b
--- /dev/null
+++ b/gitnexus/test/fixtures/lang-resolution/csharp-collection-accessor/Services/Renderer.cs
@@ -0,0 +1,17 @@
+using System.Collections.Generic;
+using Models;
+
+namespace Services;
+
+public class Renderer
+{
+ private Dictionary _widgets = new();
+
+ public void RenderAll()
+ {
+ foreach (var w in _widgets.Values)
+ {
+ w.Render();
+ }
+ }
+}
diff --git a/gitnexus/test/fixtures/lang-resolution/csharp-overload-interface/App/Caller.cs b/gitnexus/test/fixtures/lang-resolution/csharp-overload-interface/App/Caller.cs
new file mode 100644
index 000000000..8a2523381
--- /dev/null
+++ b/gitnexus/test/fixtures/lang-resolution/csharp-overload-interface/App/Caller.cs
@@ -0,0 +1,14 @@
+using Greeting;
+
+namespace App;
+
+public class Caller
+{
+ private Logger _logger = new();
+
+ public string Run(IGreeter greeter)
+ {
+ _logger.Log("starting", 1);
+ return greeter.Greet();
+ }
+}
diff --git a/gitnexus/test/fixtures/lang-resolution/csharp-overload-interface/App/Logger.cs b/gitnexus/test/fixtures/lang-resolution/csharp-overload-interface/App/Logger.cs
new file mode 100644
index 000000000..1faa0cd13
--- /dev/null
+++ b/gitnexus/test/fixtures/lang-resolution/csharp-overload-interface/App/Logger.cs
@@ -0,0 +1,12 @@
+namespace App;
+
+public class Logger
+{
+ public void Log(string message)
+ {
+ }
+
+ public void Log(string message, int level)
+ {
+ }
+}
diff --git a/gitnexus/test/fixtures/lang-resolution/csharp-overload-interface/Greeting/EnGreeter.cs b/gitnexus/test/fixtures/lang-resolution/csharp-overload-interface/Greeting/EnGreeter.cs
new file mode 100644
index 000000000..9da61a945
--- /dev/null
+++ b/gitnexus/test/fixtures/lang-resolution/csharp-overload-interface/Greeting/EnGreeter.cs
@@ -0,0 +1,9 @@
+namespace Greeting;
+
+public class EnGreeter : IGreeter
+{
+ public string Greet()
+ {
+ return "hello";
+ }
+}
diff --git a/gitnexus/test/fixtures/lang-resolution/csharp-overload-interface/Greeting/FrGreeter.cs b/gitnexus/test/fixtures/lang-resolution/csharp-overload-interface/Greeting/FrGreeter.cs
new file mode 100644
index 000000000..4c68c408c
--- /dev/null
+++ b/gitnexus/test/fixtures/lang-resolution/csharp-overload-interface/Greeting/FrGreeter.cs
@@ -0,0 +1,9 @@
+namespace Greeting;
+
+public class FrGreeter : IGreeter
+{
+ public string Greet()
+ {
+ return "bonjour";
+ }
+}
diff --git a/gitnexus/test/fixtures/lang-resolution/csharp-overload-interface/Greeting/IGreeter.cs b/gitnexus/test/fixtures/lang-resolution/csharp-overload-interface/Greeting/IGreeter.cs
new file mode 100644
index 000000000..395f301ef
--- /dev/null
+++ b/gitnexus/test/fixtures/lang-resolution/csharp-overload-interface/Greeting/IGreeter.cs
@@ -0,0 +1,6 @@
+namespace Greeting;
+
+public interface IGreeter
+{
+ string Greet();
+}
diff --git a/gitnexus/test/fixtures/lang-resolution/csharp-overload-interface/OverloadInterface.csproj b/gitnexus/test/fixtures/lang-resolution/csharp-overload-interface/OverloadInterface.csproj
new file mode 100644
index 000000000..ec2cce143
--- /dev/null
+++ b/gitnexus/test/fixtures/lang-resolution/csharp-overload-interface/OverloadInterface.csproj
@@ -0,0 +1,5 @@
+
+
+ net8.0
+
+
diff --git a/gitnexus/test/fixtures/lang-resolution/csharp-using-static/App/Calculator.cs b/gitnexus/test/fixtures/lang-resolution/csharp-using-static/App/Calculator.cs
new file mode 100644
index 000000000..881243b1c
--- /dev/null
+++ b/gitnexus/test/fixtures/lang-resolution/csharp-using-static/App/Calculator.cs
@@ -0,0 +1,11 @@
+using static Helpers.MathUtils;
+
+namespace App;
+
+public class Calculator
+{
+ public int Compute(int value)
+ {
+ return Square(value);
+ }
+}
diff --git a/gitnexus/test/fixtures/lang-resolution/csharp-using-static/Helpers/MathUtils.cs b/gitnexus/test/fixtures/lang-resolution/csharp-using-static/Helpers/MathUtils.cs
new file mode 100644
index 000000000..8fb070c39
--- /dev/null
+++ b/gitnexus/test/fixtures/lang-resolution/csharp-using-static/Helpers/MathUtils.cs
@@ -0,0 +1,9 @@
+namespace Helpers;
+
+public static class MathUtils
+{
+ public static int Square(int x)
+ {
+ return x * x;
+ }
+}
diff --git a/gitnexus/test/fixtures/lang-resolution/csharp-using-static/UsingStatic.csproj b/gitnexus/test/fixtures/lang-resolution/csharp-using-static/UsingStatic.csproj
new file mode 100644
index 000000000..ec2cce143
--- /dev/null
+++ b/gitnexus/test/fixtures/lang-resolution/csharp-using-static/UsingStatic.csproj
@@ -0,0 +1,5 @@
+
+
+ net8.0
+
+
diff --git a/gitnexus/test/integration/resolvers/csharp.test.ts b/gitnexus/test/integration/resolvers/csharp.test.ts
index 31c49378c..e2cf06850 100644
--- a/gitnexus/test/integration/resolvers/csharp.test.ts
+++ b/gitnexus/test/integration/resolvers/csharp.test.ts
@@ -197,6 +197,100 @@ describe('C# member-call resolution', () => {
});
});
+// ---------------------------------------------------------------------------
+// Collection-accessor unwrap (Unit 6c): data.Values on Dictionary
+// resolves to the value type's class.
+// ---------------------------------------------------------------------------
+
+describe('C# collection-accessor unwrap', () => {
+ let result: PipelineResult;
+
+ beforeAll(async () => {
+ result = await runPipelineFromRepo(path.join(FIXTURES, 'csharp-collection-accessor'), () => {});
+ }, 60000);
+
+ it('resolves RenderAll → Render through Dictionary.Values', () => {
+ const calls = getRelationships(result, 'CALLS');
+ const renderCall = calls.find((c) => c.source === 'RenderAll' && c.target === 'Render');
+ expect(renderCall).toBeDefined();
+ expect(renderCall!.targetFilePath).toBe('Models/Widget.cs');
+ expect(['import-resolved', 'global']).toContain(renderCall!.rel.reason);
+ });
+});
+
+// ---------------------------------------------------------------------------
+// using-static member injection (Unit 6d): `using static X.Y;` exposes Y's
+// static methods as free-callables in the consumer.
+// ---------------------------------------------------------------------------
+
+describe('C# using static member injection', () => {
+ let result: PipelineResult;
+
+ beforeAll(async () => {
+ result = await runPipelineFromRepo(path.join(FIXTURES, 'csharp-using-static'), () => {});
+ }, 60000);
+
+ it('resolves Compute → Square via `using static Helpers.MathUtils;`', () => {
+ const calls = getRelationships(result, 'CALLS');
+ const sqCall = calls.find((c) => c.source === 'Compute' && c.target === 'Square');
+ expect(sqCall).toBeDefined();
+ expect(sqCall!.targetFilePath).toBe('Helpers/MathUtils.cs');
+ expect(['import-resolved', 'global']).toContain(sqCall!.rel.reason);
+ });
+});
+
+// ---------------------------------------------------------------------------
+// Overload disambiguation + interface dispatch (Unit 6e).
+// ---------------------------------------------------------------------------
+
+describe('C# overload disambiguation and interface dispatch', () => {
+ let result: PipelineResult;
+
+ beforeAll(async () => {
+ result = await runPipelineFromRepo(path.join(FIXTURES, 'csharp-overload-interface'), () => {});
+ }, 60000);
+
+ it('Run → Log resolves to the 2-arg overload (arity narrowing)', () => {
+ const calls = getRelationships(result, 'CALLS');
+ const logCalls = calls.filter((c) => c.source === 'Run' && c.target === 'Log');
+ // With collapse-by-caller-target enabled and arity narrowing, Run
+ // should bind to the 2-arg overload only — not the 1-arg sibling.
+ expect(logCalls.length).toBe(1);
+ // Verify targetId points to the 2-arg overload by checking the
+ // target Method node's parameterTypes length.
+ const target = result.graph.getNode(logCalls[0].rel.targetId);
+ expect(target).toBeDefined();
+ const parameterTypes = (target!.properties as { parameterTypes?: string[] }).parameterTypes;
+ expect(parameterTypes).toBeDefined();
+ expect(parameterTypes!.length).toBe(2);
+ });
+
+ it('Run → Greet emits primary edge to IGreeter.Greet plus interface-dispatch siblings', () => {
+ const calls = getRelationships(result, 'CALLS');
+ const greetCalls = calls.filter((c) => c.source === 'Run' && c.target === 'Greet');
+ // One primary edge (IGreeter.Greet) + two interface-dispatch edges
+ // (EnGreeter.Greet, FrGreeter.Greet).
+ expect(greetCalls.length).toBe(3);
+
+ const primaries = greetCalls.filter((c) => c.rel.reason !== 'interface-dispatch');
+ expect(primaries.length).toBe(1);
+ expect(primaries[0].targetFilePath).toBe('Greeting/IGreeter.cs');
+
+ const fanout = greetCalls.filter((c) => c.rel.reason === 'interface-dispatch');
+ expect(fanout.length).toBe(2);
+ const fanoutPaths = fanout.map((c) => c.targetFilePath).sort();
+ expect(fanoutPaths).toEqual(['Greeting/EnGreeter.cs', 'Greeting/FrGreeter.cs']);
+ });
+
+ it('interface-dispatch fan-out excludes the primary target (no self-edge)', () => {
+ const calls = getRelationships(result, 'CALLS');
+ const fanout = calls.filter((c) => c.source === 'Run' && c.rel.reason === 'interface-dispatch');
+ for (const edge of fanout) {
+ expect(edge.targetFilePath).not.toBe('Greeting/IGreeter.cs');
+ }
+ });
+});
+
// ---------------------------------------------------------------------------
// Primary constructor resolution: class User(string name, int age) { }
// ---------------------------------------------------------------------------