Repository navigation
fix(ts): resolve static calls made through the class name - #810
kunalgoesbyken wants to merge 1 commit into
Conversation
`Cache.create()` names the class itself as the receiver, but a TS/JS
receiver with no local binding gave no type, so the call was dropped and
`callers Cache.create` found nothing, in the same file or imported.
Read a capitalised receiver as the class when the file declares that class
or imports it by name from a relative module (an alias maps to the class's
own name). An external, default or namespace import, a local value such as
`const Cache = {...}`, and a parameter or nested declaration of the same
name are not the class and still drop, as does a class that owns no such
method (`Math.max`).
🌱 graft blast radius1 area changed → 2 areas can be affected. 4 dependent symbols, depth 2. flowchart TB
A0(("Graph Construction<br/>3 symbols"))
A1(("Overlap Detection<br/>1 symbol"))
classDef reached fill:#D9EDF3,stroke:#3AA7C9,stroke-width:1.5px,color:#0E313C;
class A0,A1 reached;
Who knows this code — 3 people across 3 areas
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 All 4 dependent symbols, grouped by areaGraph Construction — 3 symbols in 3 files
Overlap Detection — 1 symbol in 1 file
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.
12 test suites also reference this code16 symbols, kept out of the diagram and the table so they cannot crowd out the areas a reviewer has to look at.
Open the interactive graph → — click an area to see its dependent symbols at file:line. |
Summary
Cache.create()names the class as the receiver, but a TS/JS receiver with no local binding got no type, so the call was dropped andcallers Cache.createfound nothing, in the same file or imported.Changes
extract.ts: collect the names that stand for a class in a file: a class declared there, and a named import from a relative module, mapped to the class's own name (import { Cache as Store }readsStoreasCache). A function drops any of these names it declares again, as a local, a parameter (including an arrow callback's), a nested function or a class.bindings.ts:resolveRecvTypereads a receiver in that set as the class. An external, default or namespace import, and a local value such asconst Cache = {...}, are not in it and still drop. A class that owns no such method (Math.max,Promise.all) finds no owner-qualified match and drops as before.Two classes with the same name in different files stay ambiguous and drop, and a static and an instance method of the same name in one class still collapse to one target, both as before.
Testing
On Windows 11 with Node 26:
test/graph-ts-static.test.ts(new): same-file, imported and.jscalls, a capitalised receiver without the method and a parameter named like a class, and the cases that must not resolve: an external named, default or namespace import, a local object named like the class, a callback parameter that shadows it (with a later call in the same file still resolving), and an aliased relative import that does. All three fail on main.test/graph*,blast*,ask*,generic*,depth*,resolve*andcovers*suites: 675 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.Fixes #809