Skip to content

feat(js): functions that call a method on an imported constant now appear as its callers - #523

Merged
bompus merged 2 commits into
fork/consolidatedfrom
feat/imported-constant-links
Oct 18, 2026
Merged

bompus merged 2 commits into
fork/consolidatedfrom
feat/imported-constant-links

Conversation

@bompus

@bompus bompus commented Oct 18, 2026 •

Copy link
Copy Markdown
Owner

callers on an imported constant now lists the functions that call a method on it. LIST.includes(x) after import { LIST } from './constants', store.get(k) through a default import and useStore.setState() through an aliased one get a calls edge from the calling function to the constant, in JavaScript, TypeScript, Vue, Svelte and Astro. Before, the fork linked a call through an import only to a function, method, class or component (or to a store through its getState), so these calls were invisible to callers and impact: on supabase, callers safeLocalStorage lists 29 files and no functions in the fork, against 43 functions in upstream baf19067.

Change

One condition in bound_receiver_claim (codegraph-kernel/src/resolve/method_call.rs, JavaScript/TypeScript branch) accepted a constant or variable only when the method was getState. It now accepts one for any method. The guards stay as they were:

  • A name a parameter or local hides (({ expect }) => expect.getState()) resolves to that binding, not the import, so it links nothing.
  • A name a Svelte markup block declares ({#each rows as count}, {#snippet item(count)}, {#await p then count}, {@const count = row}) does not reach the script's import of that name. Markup has no binding rows, so the template scan in src/extraction/svelte-extractor.ts now tracks the names the enclosing blocks declare and skips calls rooted at them (found by the Greptile review; it applies to imported functions too). A call after the block closes still links.
  • A deeper chain (supabase.auth.signUp()) is refused before the kind check.
  • A receiver whose module never resolves is still not guessed by its method's name.

The seven link expectations in sync-import-member-retry.test.ts go back to upstream's. Four more expectations in js-family-receiver-fixes, kernel-resolve-parity and resolution were written for the old rule and now expect the link to the constant (each stays unlinked to an unrelated same-named function or class method). A new test, imported-constant-member-calls.test.ts, covers a constant, a variable, a shadowing parameter and local, a deeper chain and the Svelte block forms above; it fails on the base kernel and passes here.

Evidence

From a read-only study of the base fork (5b5ac434) against upstream baf19067 on vite, vitest, svelte and supabase:

  • Upstream adds 4,426 links of this kind that the fork lacks. 156 seeded samples read against source: 153 correct, 3 ambiguous (deep chains), none wrong. Screening all 4,426 against the fork's binding rows finds 15 wrong, all in vitest, where a parameter shadows the import; this change makes none of them.
  • This change on the same corpora: vite +1,362 call edges (+4.9%), vitest +2,595 (+3.7%), svelte +135 (+0.2%), supabase +1,662 (+0.5%), none lost. It reproduces 4,006 of upstream's 4,426 and makes 1,748 more (the fork follows ~utils aliases and export * chains that upstream does not); a seeded sample of 49 of those read 49 correct.
  • Most added edges are in test and playground code: vi and expect account for 1,910 of vitest's links, and 1,217 of vite's land on one Playwright page variable.
  • I reproduced the vite, vitest and svelte edge totals on this head (29,238 / 72,769 / 59,520). Supabase and the sampling come from the study.

Checks

On head 178cd22e:

Check Result
npm run build:kernel (clippy -D warnings) exit 0
npx vitest run (full) 751 files, 9,293 passed, 40 skipped, 0 failed
kernel-golden-dumps with UPDATE_GOLDEN=1 8 passed, no .dump changed
eval:precision vite, vitest, svelte exit 0; known-wrong cases absent 6/6, 1/1, 1/1; controls present 2/2 on vite; svelte edge total 59,519 (59,520 before the markup fix)
npx tsc --noEmit, npm run check:agent-docs, readme-sync exit 0
New test on the base kernel fails ([] against the two expected links)

Index time shows no clear change (vite 4.0 s either way; one run each).

README rows checked

  • Kept-resolution paragraph (line 128): its sentence that a call on an imported constant stays unresolved is replaced with the new behavior.
  • "About this fork" tables and the full-index numbers: unchanged; this adds 0.2-4.9% edges and no measured time.
  • CHANGELOG: new Fixes entry; the fork-only note that these calls stay unlinked after a sync is removed; the Kotlin entry's "7% and 6% more peak memory" now says it holds for that change alone.

Not covered

  • Links to static class members (22 vitest calls such as TestRunner.getCurrentTest(), all correct in the sample) still need property targets and stay unlinked.
  • Whether these should be references rather than calls for receivers that are not functions.
  • Arrow-function parameters inside a markup expression (rows.map((count) => count.set(1))) in Svelte and Astro still resolve to a script import of the same name; the gap already existed for imported functions.
  • Kotlin, Java, Python and the other languages: only the JavaScript/TypeScript branch changes.
  • Promoting the build: separate step.

Summary by cubic

A member call on an imported constant or variable now links to that constant, so callers on one lists the functions that use it, not only the files that import it.

Before, a call through an import linked only to a function, method, class or component, or to a store through its getState. Now LIST.includes(x) after import { LIST } from './constants', store.get(k) through a default import and useStore.setState() through an aliased one give the calling function a calls edge to the constant, in JavaScript, TypeScript, Vue, Svelte and Astro.

  • A name a parameter, a local or a Svelte markup block hides — ({ expect }) => expect.getState(), {#each rows as count} — a deeper chain like config.api.fetch(), and a receiver whose module never resolves still link nothing.
  • Added tests cover a constant, a variable, shadowed names, a deeper chain and Svelte markup blocks; existing expectations are updated to match.
  • Full-index edge totals rise 0.2–4.9% on vite, vitest, svelte and supabase with none lost; most added edges land in test and playground code.
  • Re-index JavaScript and TypeScript projects after upgrading.

Written for commit 178cd22. Summary will update on new commits.

View guided diff Turn on auto-fix

…pear as its callers

A member call through an import (`LIST.includes(x)` after
`import { LIST } from './constants'`, `store.get(k)`) linked only to a
function, method, class or component, or to a store through `getState`.
It now also links to an imported constant or variable, as upstream does,
so `callers` on a constant lists the functions that use it, not only the
files that import it.

A name a parameter or local hides, and a deeper chain such as
`config.api.fetch()`, still link nothing, and a receiver whose module never
resolves is still not guessed by its method's name.

The seven sync expectations that had moved away from upstream's move back,
four fork-policy expectations in the receiver, parity and resolution tests
now expect the link to the constant, and a new test covers a constant, a
variable, a shadowing parameter and local, and a deeper chain.
@coderabbitai

coderabbitai Bot commented Oct 18, 2026 •

Copy link
Copy Markdown

Important

  • 🔍 Trigger review

This repository does not receive automatic reviews because it has fewer than 10 stars.

⚙️ Run configuration
  • Configuration used: Repository YAML (base), Organization UI (inherited)
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 20d103d3-fe3e-44ab-827d-20315406ff9f
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@greptile-apps

greptile-apps Bot commented Oct 18, 2026 •

Copy link
Copy Markdown

RetriggerView in GreptileConfidence Score: 4/5

[Medium impact] Changes how method calls on imported constants are resolved.

Fix the false links from Svelte template locals before merging.

Findings

  1. P1 Loop locals become store callers ▶
Fix with agent prompt
### Issue 1
codegraph-kernel/src/resolve/method_call.rs:1472-1476
With `import { count } from './stores'`, a `{count.set(1)}` expression inside `{#each rows as count}` uses the loop's `count`, not the import. Template locals have no binding rows, so `bound_receiver_claim` falls back to the script import. Accepting `constant` here creates a false `calls` edge, making callers and impact results misleading.

Account for template-local names before accepting the imported constant, and add a regression test for this case.

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Summary

This PR makes member calls on imported JavaScript-family constants and variables link to those values.

  • Member calls on imported constants and variables now link to those values.

Explicitly deferred by bompus: Static class-member targets, choosing references instead of calls, other languages, and promoting the build are outside this change.

Reviews (1) · Last reviewed commit: "feat(js): functions that call a method o..." · Reviewed by Greptile

Comment thread codegraph-kernel/src/resolve/method_call.rs
…n the script's import

Calls in Svelte markup have no binding rows, so a name declared by {#each … as x}, {#snippet f(x)}, {#await … then x} or {@const x} resolved to a script import of the same name. The template scan now tracks the names the enclosing blocks declare and skips calls rooted at them. This matters more now that an imported constant takes member calls.
@bompus
bompus merged commit 559cc09 into fork/consolidated Oct 18, 2026
5 checks passed
@bompus
bompus deleted the feat/imported-constant-links branch October 18, 2026 05:41
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