diff --git a/gitnexus/test/fixtures/lang-resolution/csharp-frozen-binding-collision/App/Program.cs b/gitnexus/test/fixtures/lang-resolution/csharp-frozen-binding-collision/App/Program.cs new file mode 100644 index 0000000000..4e71ec93a7 --- /dev/null +++ b/gitnexus/test/fixtures/lang-resolution/csharp-frozen-binding-collision/App/Program.cs @@ -0,0 +1,18 @@ +using Collision.Models; + +namespace Collision.App +{ + public class User + { + public string GetName() { return "app"; } + } + + public class Program + { + public void Run() + { + var u = new User(); + u.GetName(); + } + } +} diff --git a/gitnexus/test/fixtures/lang-resolution/csharp-frozen-binding-collision/CsharpFrozenBindingCollision.csproj b/gitnexus/test/fixtures/lang-resolution/csharp-frozen-binding-collision/CsharpFrozenBindingCollision.csproj new file mode 100644 index 0000000000..4cefc0dfae --- /dev/null +++ b/gitnexus/test/fixtures/lang-resolution/csharp-frozen-binding-collision/CsharpFrozenBindingCollision.csproj @@ -0,0 +1,6 @@ + + + net8.0 + Collision + + diff --git a/gitnexus/test/fixtures/lang-resolution/csharp-frozen-binding-collision/Models/User.cs b/gitnexus/test/fixtures/lang-resolution/csharp-frozen-binding-collision/Models/User.cs new file mode 100644 index 0000000000..a02beb6722 --- /dev/null +++ b/gitnexus/test/fixtures/lang-resolution/csharp-frozen-binding-collision/Models/User.cs @@ -0,0 +1,7 @@ +namespace Collision.Models +{ + public class User + { + public string GetName() { return "models"; } + } +} diff --git a/gitnexus/test/integration/resolvers/csharp.test.ts b/gitnexus/test/integration/resolvers/csharp.test.ts index b412ecc9a7..1d41bb1708 100644 --- a/gitnexus/test/integration/resolvers/csharp.test.ts +++ b/gitnexus/test/integration/resolvers/csharp.test.ts @@ -2485,3 +2485,50 @@ describe('C# large-file + frozen-bucket regression (issue #1066)', () => { expect(['import-resolved', 'global']).toContain(save!.rel.reason); }); }); + +// --------------------------------------------------------------------------- +// Issue #1066 companion regression: small-file trigger for the same +// frozen-bucket failure. Where csharp-large-cache-miss-resolution exercises +// the path through tree-sitter cache-miss reparse on >32 KB files, this +// fixture trips the same `Object.freeze` contract on the populator's +// namespace-import loop in a single small file pair: the importer locally +// declares a class with the same simple name as a sibling reachable through +// `using`, so the extractor pre-populates (and freezes) `User` in the +// importer's Module bindings before populateNamespaceSiblings tries to +// append the cross-file `Collision.Models.User`. Pre-#1082 the populator +// pushed onto the frozen array → "Cannot add property N, object is not +// extensible" → whole scopeResolution phase aborted. Post-#1082 the +// augmentation channel keeps both bindings visible to readers, with the +// local `Collision.App.User` taking precedence per origin ordering. +// --------------------------------------------------------------------------- + +describe('C# frozen-binding collision via using-import (issue #1066 companion)', () => { + let result: PipelineResult; + + beforeAll(async () => { + result = await runPipelineFromRepo( + path.join(FIXTURES, 'csharp-frozen-binding-collision'), + () => {}, + ); + }, 60000); + + it('completes scopeResolution without throwing on the colliding bucket', () => { + expect(getNodesByLabel(result, 'Class')).toEqual(expect.arrayContaining(['User', 'Program'])); + }); + + it('detects both User declarations across the two namespaces', () => { + const users = getNodesByLabelFull(result, 'Class').filter((n) => n.name === 'User'); + expect(users.length).toBe(2); + const paths = users.map((u) => u.properties.filePath).sort(); + expect(paths).toEqual(['App/Program.cs', 'Models/User.cs']); + }); + + it('resolves Program.Run -> local Collision.App.User constructor (origin:local shadows namespace)', () => { + const calls = getRelationships(result, 'CALLS'); + const ctor = calls.find( + (c) => c.source === 'Run' && c.target === 'User' && c.targetLabel === 'Class', + ); + expect(ctor).toBeDefined(); + expect(ctor!.targetFilePath).toBe('App/Program.cs'); + }); +});