Skip to content

fix(resolution): a same-name re-binding is not a local definition - #1760

Open
danusha2345 wants to merge 3 commits into
colbymchenry:mainfrom
danusha2345:fix/1714-rebinding-not-local
Open

fix(resolution): a same-name re-binding is not a local definition#1760
danusha2345 wants to merge 3 commits into
colbymchenry:mainfrom
danusha2345:fix/1714-rebinding-not-local

Conversation

@danusha2345

Copy link
Copy Markdown
Contributor

Follow-up to #1759 (the landing of #1735). Fixes a regression that is on main now: object-literal-methods.test.ts and ui-steps-api.test.ts fail at cd4e65b (3 tests), because the local-binding rule reads a store-action re-binding as a local definition.

What

const { fetchUser } = useStore.getState() and const setZipUri = useStore((s) => s.setZipUri) are how a store action reaches its caller, and the store-action resolution follows exactly those shapes. Rule 2 of #1759 ("a name the file binds itself has no cross-file candidate") counted both as definitions and dropped loginFlow → fetchUser and handleZipComplete → setZipUri — edges the graph is built to hold.

A declaration whose pattern or initializer names the same member is a re-binding of something defined elsewhere, not a definition: the graph's symbol is what the bare call means. isLocallyBoundJsName now skips a destructuring pattern altogether and a plain const x = … whose initializer mentions x (s.setZipUri, options.now). const transform = makeTransform(), a parameter, a function/class declaration and an arrow bound to a fresh name still shadow.

The fixture's const now = options.now || (() => Date.now()) case is dropped from the "locally bound" test: by this rule it is a re-binding, and the graph's cross-file now is what it meant before #1759 too. The new test pins the store shapes.

Measured

vitejs/vite 8492422, wasm arm, edge rows keyed with resolvedBy. On main at 2f1a99d (pre-#1759) the two rules with this fix: LOST 709 / GAINED 137 — the removals are the #1714 shape (import(…)runner.ts::import 264, resolve(…)/transform(…)PluginContainer 217, a fixture's test 91, …); 86 of the gains are resolve bound by import { resolve } from 'node:path' landing on a nested const resolve in config.ts, which #1715's bare-import guard declines. Stacked on #1715: LOST 515 / GAINED 56 (41 are log(…) moving onto event.d.ts's declared global).

Tests

bare-call-no-method 6/6 (one new: a hook selector and a getState() destructure keep their edges), object-literal-methods and ui-steps-api pass again, resolution 198/198, cross-file-visibility, frameworks-integration; tsc clean. Full suite on Linux: only the viewer-less codegraph ui / ui-package files fail here, same as on main.

🤖 Generated with Claude Code

`const { fetchUser } = useStore.getState()` and `const setZipUri =
useStore((s) => s.setZipUri)` are how a store action reaches its caller;
the local-binding rule read both as definitions and dropped the
cross-file edge the store-action resolution exists to hold
(object-literal-methods, ui-steps-api). A declaration whose pattern or
initializer names the same member is a re-binding of something defined
elsewhere: the graph's symbol is what the bare call means.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
(cherry picked from commit afa69fc)
`const now = opts.now || Date.now` is a local binding after all: on a
Kotlin + JS app the wider "initializer mentions the name" exemption sent
24 `now()` calls onto a Kotlin test's `private val now`. A re-binding is
a destructuring pattern or an arrow that picks the member off its own
parameter (`useStore((s) => s.setZipUri)`); `() => Date.now()` is not
one. The `options.now` fixture is back in the test.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@danusha2345

Copy link
Copy Markdown
Contributor Author

Second commit, a29d112: the exemption was too wide. On a Kotlin + JS + Go app, const now = opts.now || Date.now read as a re-binding and 24 now() calls in the renderer landed on a Kotlin test's private val now — that alias IS a local binding, nothing in the graph is what the call means. A re-binding is now only a destructuring pattern or a selector arrow that picks the member off its own parameter (useStore((s) => s.setZipUri)); () => Date.now() is not one. The options.now fixture is back in the test. That app: −509 / +13 against main, the 13 all rcjoystick.js onto stick-curve.js (real). The three store-action tests still pass.

bompus added a commit to bompus/codegraph that referenced this pull request Sep 8, 2026
Replaces the fork-local carve-out with the version in upstream PR colbymchenry#1760,
which fixes the same colbymchenry#1759 regression. Adopting it now means the merge is
clean when colbymchenry#1760 lands instead of conflicting in name-matcher.ts.

The two differ in approach. The carve-out kept destructuring in declRe and
excluded `.getState()` / `get()` initialisers by name; colbymchenry#1760 drops the
destructuring alternation from declRe entirely, so a destructured binding is
never a candidate, and matches a selector by backreference — the arrow's body
must read the member off its OWN parameter. That also reclassifies
`const now = opts.now || (() => Date.now())`, which the carve-out kept
shadowing.

bare-call-no-method, object-literal-methods and ui-steps-api: 25 passed,
including colbymchenry#1760's new store-selector test, carried over with it.
@danusha2345

Copy link
Copy Markdown
Contributor Author

Merged current main (3ed73bc) into this branch: head 2b126b6, no conflicts. On that merge the two ui-steps-api tests and the loginFlow → fetchUser assertion of object-literal-methods go green (the three #1759 regressions this PR is for). What is left red in that file is a different assertion — hardReset → reset through useStore.getState().reset() — and it is red on plain main since de5adba (#1790 drops the identifier-rooted member call), see #1794. This PR does not touch that path.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant