From cfe4e49c416039664aed59fa9806a1e2d38f1339 Mon Sep 17 00:00:00 2001 From: Gergo Magyar Date: Sat, 30 May 2026 11:01:47 +0000 Subject: [PATCH] test(go): strengthen func_literal smoke case to a positive receiver assertion (#1848 U3) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The old case used a closure-only source and only asserted ABSENCE of @type-binding.self, so it would pass even if the method_declaration receiver branch regressed (Codex F3). The fixture now has both a method and a closure, and positively asserts exactly one @type-binding.self from the method (name=u, type=User — the type also confirms *User pointer-stripping) and none from the closure. Co-Authored-By: Claude Opus 4.8 (1M context) --- .../go/go-captures-smoke.test.ts | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/gitnexus/test/unit/scope-resolution/go/go-captures-smoke.test.ts b/gitnexus/test/unit/scope-resolution/go/go-captures-smoke.test.ts index 1e878cfc4..cd67dbffb 100644 --- a/gitnexus/test/unit/scope-resolution/go/go-captures-smoke.test.ts +++ b/gitnexus/test/unit/scope-resolution/go/go-captures-smoke.test.ts @@ -66,20 +66,31 @@ func main() { // ── Edge shapes the #1915 captured-node refactor reasons about but no // lang-resolution fixture exercises (issue #1848 follow-up U2). ── - it('captures a func_literal as a scope without synthesizing a receiver', () => { + it('synthesizes a receiver for a method but not for a func_literal scope', () => { + // Source has BOTH a real method and a closure. A weak "no @type-binding.self + // anywhere" assertion would pass even if the method_declaration receiver + // branch regressed (a closure-only fixture has none to lose); asserting the + // method's receiver IS present catches that regression. const src = ` package main +type User struct{ Name string } + +func (u *User) Save() { _ = u.Name } + func main() { f := func() int { return 1 } _ = f() } `; const matches = emitGoScopeCaptures(src, 'main.go'); - // The closure is captured as a @scope.function... + // The closure is still captured as a @scope.function... expect(matches.some((m) => m['@scope.function']?.text.startsWith('func()'))).toBe(true); - // ...but a func_literal has no receiver, so no self type-binding is synthesized. - expect(matches.every((m) => m['@type-binding.self'] === undefined)).toBe(true); + // ...and the method's receiver self-binding is synthesized (name + pointer-stripped type)... + const selves = matches.filter((m) => m['@type-binding.self'] !== undefined); + expect(selves).toHaveLength(1); // exactly one — from the method, not the closure + expect(selves[0]!['@type-binding.name']?.text).toBe('u'); + expect(selves[0]!['@type-binding.type']?.text).toBe('User'); }); it('does not drop a var-form type assertion binding', () => {