Repository navigation
fix(go): resolve calls through typed function and method parameters - #808
kunalgoesbyken wants to merge 1 commit into
Conversation
A Go function gets its collaborators as parameters, but only `:=`, `var`
and struct fields were bound to a type. `func handle(s *Server) { s.Start() }`
had no receiver type, so the call was dropped and `callers Server.Start`
missed every caller that is handed the server instead of building it.
Bind each parameter of a declared function or method (grouped names and
named results included) to its type.
A name declared again with a type we cannot read (a func literal
parameter, a `:=` from an untyped call, a range or type-switch variable)
now hides the outer binding instead of inheriting it, so `s.Start()` under
`s := other()` no longer resolves to the parameter's type.
🌱 graft blast radiusNothing outside this diff depends on it. 1 area changed; no indexed dependents at depth 2. Who knows this code — 1 person across 1 area
Ownership is git history over each area's own files, weighted towards recent work (120-day half-life). Merge commits and bots are dropped, and you are dropped from your own PR. A name with no Test signal per changed area — 1 ✗Reached = a node under a test path has a resolved edge into the changed symbol. It undercounts anything called indirectly — through a CLI, a spawned process or a dynamic import — so read a low ratio as “look here”, never as a coverage gate.
Open the interactive graph → — click an area to see its dependent symbols at file:line. |
Summary
In Go a parameter is the usual way a function gets hold of another type, but
func handle(s *Server) { s.Start() }produced no call edge:handleGonever bound parameters, soresolveRecvTypereturned nothing and the member call was dropped.callers Server.Startmissed every caller that is handed the server instead of building it.Changes
bindings.ts: inhandleGo, bind eachparameter_declarationof afunction_declarationormethod_declarationto its type. Grouped names (a, b *T) and named results are included. Qualified (http.Request), slice, map and variadic types bind nothing.:=from an untyped call, avar x = f(), a range variable, a receive or type-switch variable. Without this,s := other(); s.Start()insidefunc f(s *Server)resolved toServer.Start.FileBindings.shadowstores a blank type,lookupstops at it andsetnever overwrites it. Only the Go handler writes it.Testing
On Windows 11 with Node 26:
test/graph-go-params.test.ts(new). The first test covers pointer, value, grouped and named-result parameters, a method's own parameter, and a slice parameter that must not bind. The second covers a func literal parameter, an untyped:=, a range variable and a multi-value:=hiding the typed parameter, with an unshadowed call still resolving. Both fail on main.test/graph*,blast*,ask*,generic*,depth*,resolve*andcovers*suites: 674 tests, 1 fail. The one failure isdiscoverWorkspaceChildren follows a symlinked child repo, a symlink permission error on Windows that fails the same way on main.tsc --noEmitpasses.On seedfall (84 Go files plus examples),
callsedges go from 3318 to 3408: 92 added, 2 removed. Added edges are calls on parameters, such asengine/build.go#Build -> engine/config.go#Config.specs. The two removed are real calls (memFS.OpenFile -> memFile.TruncateandmainPackages -> mainPackage.matches). Bindings are one map per function, so a name that is also declared untyped, or as a func literal parameter, elsewhere in the same function is left unresolved instead of guessed.Fixes #807