fix(go): require URL-shaped paths for route detection (#1308)

cache.Put("a", 1), store.Get("config", out), bus.Handle("user.created",
h) — any verb-named method with a string first arg — were indexed as
HTTP routes (38 of 82 route nodes were false positives on the
reporter's 200 KLOC Go codebase). A registration's first argument must
now start with "/" (every router style), or be a Go 1.22
"METHOD /path" mux pattern on Handle/HandleFunc — which now also
extracts the real method instead of ANY.

Validated on go-chi/chi (212 real routes retained, all path-shaped)
and golang/groupcache (0 route nodes).

Fixes #1259

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Colby Mchenry
2026-07-16 14:59:00 -05:00
committed by GitHub
co-authored by Claude Fable 5
parent 30421953ac
commit e1f339f732
3 changed files with 60 additions and 5 deletions
+31
View File
@@ -942,6 +942,37 @@ describe('goResolver.extract', () => {
const { references } = goResolver.extract!('routes.go', src);
expect(references[0].referenceName).toBe('listUsers');
});
it('does NOT treat verb-named method calls with non-path args as routes (#1259)', () => {
// The issue's repro: a generic cache type whose Put/Get share router verb
// names. First args are keys, not URL paths — no route nodes.
const src = [
`c.Put("a", 1)`,
`c.Put("user:123", value)`,
`store.Get("config", out)`,
`bus.Handle("user.created", onUserCreated)`,
`m.HandleFunc("shutdown", hook)`,
].join('\n');
const { nodes } = goResolver.extract!('cache.go', src);
expect(nodes).toHaveLength(0);
});
it('keeps real registrations whose paths start with "/" for every router style', () => {
const src = [
`r.Put("/users/{id}", updateUser)`, // chi
`v1.GET("/ping", ping)`, // gin group
`mux.HandleFunc("/healthz", health)`, // net/http
].join('\n');
const { nodes } = goResolver.extract!('routes.go', src);
expect(nodes.map((n) => n.name)).toEqual(['PUT /users/{id}', 'GET /ping', 'ANY /healthz']);
});
it('recognizes Go 1.22 "METHOD /path" patterns on HandleFunc and extracts the method', () => {
const src = `mux.HandleFunc("GET /api/users/{id}", getUser)\n`;
const { nodes, references } = goResolver.extract!('main.go', src);
expect(nodes[0].name).toBe('GET /api/users/{id}');
expect(references[0].referenceName).toBe('getUser');
});
});
import { goframeResolver } from '../src/resolution/frameworks/goframe';