Skip to content

fix(extraction): never fabricate an edge from a call-result receiver - #1692

Open
danusha2345 wants to merge 1 commit into
colbymchenry:mainfrom
danusha2345:fix/1683-call-receiver-chains
Open

fix(extraction): never fabricate an edge from a call-result receiver#1692
danusha2345 wants to merge 1 commit into
colbymchenry:mainfrom
danusha2345:fix/1683-call-receiver-chains

Conversation

@danusha2345

Copy link
Copy Markdown
Contributor

Fixes #1683. Also covers the false-positive half of #1681.

Problem

A member call whose receiver is itself a call — d.setdefault(k, []).append(v), d.items().get(k), make().run() — lost the receiver at extraction time and degraded to the bare method name. The bare name then exact-matched (or, via the fuzzy split, fuzzy-matched) any top-level project symbol of that name — a calls edge from an unrelated function, reproduced in Python and JavaScript alike, so it is the shared extractor, not a per-language rule.

Change

  • Extraction (wasm walker, tsjs/extractors.rs, python.rs): for TS/JS/Python a call receiver is kept and encoded as <inner>().<method> — the marker the Java / Kotlin / C++ chains already use, which no plain name can match. An inner callee with no static name ((await x)(), arr[0]()) emits nothing: a silent miss, never a wrong edge. The inner call is visited on its own either way, so make() keeps its edge.
  • Resolution: the chain shape is routed past resolveViaImport (which bound useStore.getState().reset to the imported store constant, so the method was never looked up) and stops before the fuzzy strategy for these three languages. The one fallback kept is the store-accessor idiom the object-literal coverage relies on — Zustand's get() inside the factory and useStore.getState() outside it, followed by a method name with exactly one callable in the project. Everything else resolves to nothing: what an inner call returns is not knowable from its name (an earlier draft that allowed any project-rooted chain bound db.prepare(sql).all() to a project function named all on this repo's own index — 363 such edges — which is the very defect).
  • Parity fixtures: torture.js and torture.py gain the shapes.

Verification

  • New __tests__/call-receiver-no-fabrication.test.ts: the issue's Python and JS repros produce no edge into the same-named top-level functions, the inner call keeps its edge, the encoding is as stated, a receiver with no static callee is dropped. On main the fabricated append / get / run callers appear.
  • object-literal-methods (Zustand get().reset() and useStore.getState().reset()) still resolves; its extraction assertion is updated to the chain-encoded ref.
  • Full suite with the rebuilt kernel: 237 files, 4234 passed, 9 skipped.
  • On real repositories (a TS/Dart app, a Kotlin+Go+TS app, this repo, a 4k-file C tree): cross-file calls edges landing on top-level functions named like collection methods drop from 22 → 5, 31 → 20, 2 → 1; C unchanged.

Re-index after upgrading.

🤖 Generated with Claude Code

…olbymchenry#1683, colbymchenry#1681)

A member call whose receiver is itself a call — `d.setdefault(k,
[]).append(v)`, `make().run()` — lost the receiver at extraction and
degraded to the bare method name, which exact-matched (or fuzzy-matched)
any top-level project symbol of that name: a call edge from an unrelated
function, in Python and JavaScript alike. Keep the inner callee, encoded
as `<inner>().<method>` like the Java/C++ chains, in the wasm walker and
both kernels; an inner callee with no static name emits nothing.

The resolver owns the chain shape for TS/JS/Python: it is routed past the
import strategy (which bound `useStore.getState().reset` to the imported
store constant) and never reaches the fuzzy split. The one fallback kept
is the store-accessor idiom — Zustand's `get()` / `useStore.getState()`
followed by a method name with exactly one callable in the project — which
the object-literal store coverage relies on. Everything else resolves to
nothing: what an inner call returns is not knowable from its name.
danusha2345 pushed a commit to danusha2345/codegraph that referenced this pull request Sep 5, 2026
…uiltin-method name

The extractor hunk is dropped: it changes src/extraction/tree-sitter.ts only,
which the kernel (python.rs) supersedes at runtime, and the call-receiver
shape it targets is already covered in both arms by colbymchenry#1692.
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.

Call-expression receivers drop the receiver and fabricate a calls edge to any same-named top-level symbol — Python AND JavaScript, live in 1.6.0

1 participant