Skip to content

Emit calls edges for top-level function calls, with file node as caller#2016

Open
Rishet11 wants to merge 2 commits into
Graphify-Labs:v8from
Rishet11:feat/1972-file-level-caller-for-toplevel-calls
Open

Emit calls edges for top-level function calls, with file node as caller#2016
Rishet11 wants to merge 2 commits into
Graphify-Labs:v8from
Rishet11:feat/1972-file-level-caller-for-toplevel-calls

Conversation

@Rishet11

Copy link
Copy Markdown

Fixes #1972

Problem

Calls made at a file's top level (outside any def) have no caller node, so they emit no calls edges. A function invoked only from module scope looks dead in the graph.

Fix

In graphify/extractors/engine.py, after the per-definition walk, walk the file root once more with the file node as caller. walk_calls already returns at every definition boundary, so nothing already covered gets re-emitted.

Two scoping decisions:

Test

3 new tests: top-level Python call, top-level JS call, and an in-function regression guard. Full suite shows no new failures against the v8 baseline.

One known behavior to flag: class-body statements now get attributed to the file (relevant for Swift field initializers). No test covers that yet, so I left it alone for now.

Still fairly new to this codebase, so if I have the approach or the scoping wrong anywhere, tell me and I will fix it up.

… as caller (Graphify-Labs#1972)

Calls at a file's top level (or inside a plain DSL block) had no enclosing
definition, so they never entered function_bodies and got no caller node or
edge. Walk the file root once with the file node as caller after the
per-definition walk; walk_calls already returns at every definition boundary,
so it cannot double-emit anything the per-body loop covered.

During this root walk emit ONLY direct calls: a _toplevel_calls_only flag
suppresses indirect_call (already handled by the dedicated module-dispatch
pass with correct shadow filtering) and the PHP-family reference emissions.
Java is skipped entirely (no top-level statements; field initializers are
walked via initializer_nodes with the owning class as caller).

Covers Python and JS/TS, which share this extractor. Adds tests for
top-level Python/JS calls and an in-context regression guard.
Copilot AI review requested due to automatic review settings July 19, 2026 00:00

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes a graph-extraction gap where calls made at a file’s top level (outside any function/method body) previously had no caller node and therefore emitted no calls edges. It does so by adding a second walk_calls pass rooted at the file AST root with the file node as caller_nid, while gating that pass to avoid duplicating non-calls relations handled by other module-scope passes.

Changes:

  • Add a file-root walk_calls pass (skipping Java) to emit calls edges for script/top-level call sites (#1972).
  • Introduce a _toplevel_calls_only guard to suppress indirect-dispatch and other non-calls relations during the file-root walk.
  • Add tests covering top-level Python calls, top-level JS calls, and a regression guard ensuring no duplicate/incorrect caller attribution.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
graphify/extractors/engine.py Adds a guarded file-root call walk to attribute top-level calls to the file node and avoid duplicating non-calls relations.
tests/test_extract.py Adds regression tests ensuring top-level calls now produce calls edges sourced from the file node (and that in-function calls remain unchanged).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +3612 to +3615
# #1972: during the top-level root walk, emit ONLY direct `calls` edges.
# Module-level indirect dispatch already has a dedicated pass below with
# correct module-scope shadow filtering, so a root-walk emission would be a
# duplicate carrying wrong (empty) shadow context.
Comment thread graphify/extractors/engine.py Outdated
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
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.

Calls and constant reads in top-level / script context never get a caller node, so they emit no edges (uniform across languages)

2 participants