Repository navigation
fix(queries): return constructor calls and portable recursive call edges - #1777
Conversation
find_all_callers/find_all_callees resolve by bare callee name, not import scope. On an overloaded name the resolver binds every cross-file caller to one canonical node regardless of what the caller imports. Real case (2026-09-19, kalshi-trader): GateDecision is defined twice; 13 of 14 find_all_callers edges pointed at the registry's class while the production callers construct the other one. Two failure modes are now flagged in the tool response itself: 1. Overloaded name + by-name lookup: results are prefixed with an OVERLOAD_WARNING record naming the definition count. By-path lookups are exact and pass through untouched. 2. Overloaded name + EMPTY result: annotated too, and with a sharper note — the query matches (target:Function) only, so class-instantiation edges (GateDecision is a class) do not appear here at all. 'No callers' on a multi-definition name can mean 'wrong label', not 'no callers'. The definition count runs through the same driver/session the finder already holds (label-agnostic MATCH, so classes count), and every guard failure degrades to returning the unmodified result — the annotation can never make a lookup worse. Verified against a live falkordb graph: overloaded function (12 defs, 327 edges) warns; overloaded class (2 defs, 0 visible edges) warns with the label note; by-path and unique-name lookups return silently unchanged.
…Function
find_callers/find_all_callers pinned the target to (target:Function) — five
query sites across the depth-1 and variable-length variants. Class nodes carry
CALLS edges from their constructors (instantiation), so any by-name lookup for
a class returned zero edges: a false negative indistinguishable from "no
callers". Real case: GateDecision by name returned 0; 14 direct caller edges
exist, including the four entries.py gate wrappers whose mis-attribution to
the wrong same-named class motivated this work.
Targets are now label-less with the existing name/path filters doing the work
(labels could not be disjoined on falkordb; label-less MATCH is portable).
File/Module nodes cannot collide because a lookup name does not equal a path.
The variable-length variant's caller stays (caller:Function) — instantiation
edges point INTO classes; a class being the caller-of origin is a different
question and out of scope here.
One site left untouched by design: the path-between query at L1261 pins both
endpoints via placeholder props ({start_props}/{end_props}) and is not part of
the by-name lookup surface.
With the visibility fix in place, the OVERLOAD_WARNING guard's empty-result
note is reduced accordingly (no longer claims the label exclusion as the
cause).
Co-Authored-By: Claude Code <[email protected]>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Hi! 👋 Join our CodeGraphContext Discord channel to collaborate: https://discord.gg/dR4QY32uYQ |
🔍 PR Code Graph Analysisfix(queries): return constructor calls and portable recursive call edges (#1777) 📊 Interactive VisualizationView the blast radius graph: PR Reviewer Dashboard 📦 ArtifactsThe graph JSON has been uploaded as a build artifact: Generated by CodeGraphContext using FalkorDB Lite |
|
Final combined-source audit also caught Windows separator handling: indexed node paths use forward slashes, so exact and repository-scope inputs now use Path.as_posix(), including the resolved direct-callee path. Published this focused follow-up and re-ran the 11 native/contract cases successfully. CI must pass on the new head before merge; the final combined fast suite will use this source. |
Shashankss1205
left a comment
There was a problem hiding this comment.
Ready to merge at the Windows-normalized head. Native Kuzu and Ladybug tests cover direct and recursive constructor/function lookups, repository-prefix boundaries, path/fallback behavior, heuristic calls and depth. Real Neo4j/Falkor entity conversion tests preserve relationship properties and the established edge fields, deduplication and 500-edge output cap; work is bounded to 500 paths. No overload monkey-patches are included. All current-head CI checks pass. Final combined fast suite: 1,828 passed, 8 skipped; combined website build passes.
Caller/callee lookups excluded Class targets even though CALLS can point at class constructors. Integrate the useful query changes from #1723 and preserve its original commit as a parent. The unrelated global overload-warning monkey-patches are omitted; #1724 remains open for that separate response-contract work.
Direct caller/callee queries now accept Function and Class targets. Native regressions also exposed parser/binder failures, missing startNode(), incompatible list indexing and a Kuzu crash in recursive lookups. Return bounded paths and flatten only the established five edge fields in Python, preserving real Neo4j/Falkor relationship properties, distinct-edge behavior and the existing 500-edge output cap. A 500-path work bound keeps conversion bounded. Repository prefix filters require a directory separator so /repo excludes /repo-other; the existing missing-path fallback and depth sanitization remain.
Validation: native Kuzu and Ladybug tests initially reproduced empty constructor results; all 11 focused cases now pass (direct/recursive, with/without paths, ordinary/heuristic calls, scope/depth, fallback, Neo4j/Falkor entity conversion, deduplication and cap). Full local unit suite: 1,700 passed, 8 skipped. New tests pass Ruff F/E9; the source's two pre-existing F541 diagnostics are unchanged. git diff --check passes. Full CI must pass before merge. No license changes.