Skip to content

fix(cross-repo): point a cross-repo call edge at its call site, not the caller's header - #4669

Open
xiongjianxu wants to merge 1 commit into
Graphify-Labs:v8from
xiongjianxu:fix/cross-repo-call-site-file
Open

xiongjianxu wants to merge 1 commit into
Graphify-Labs:v8from
xiongjianxu:fix/cross-repo-call-site-file

Conversation

@xiongjianxu

Copy link
Copy Markdown
Contributor

Summary

Closes #4668.

A cross-repo calls edge pointed source_file:source_location into the wrong file. source_file came from the caller node (an ObjC method node lives at its @interface in the .h) while source_location is the call-site line (in the .m), so the pair landed past the end of a short header.

Testing

Based on v8.

…he caller's header

A cross-repo `calls` edge took its `source_file` from the caller node
(an ObjC method node is minted at its `@interface` in the `.h`) while its
`source_location` is the call-site line, recorded in the `.m`. Pairing the
two pointed `source_file:source_location` into the wrong file — often past
the end of a short header.

The park payload now carries the call-site file alongside the line, and
`link_cross_repo_member_calls` prefers it, falling back to the caller
node's file for pre-Graphify-Labs#3152 graphs. The parked path is relativized in the
same extract-time pass that relativizes node source_files, so it never
leaks the absolute checkout path into graph.json.

Co-Authored-By: Claude Code <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown

Thanks for the pull request, @xiongjianxu. A maintainer will review it soon.

Want to talk it through while it is in review? Come join us on our Discord server. For longer-form discussion there is also GitHub Discussions.

A couple of things that speed up review: make sure the test suite passes on Python 3.10 and 3.13, and that the change keeps extraction deterministic.

@github-actions github-actions Bot added the contributor Pull request from a returning community contributor label Oct 22, 2026

@graphify-labs graphify-labs Bot 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.

Graphify reviewed this change.

No issues found by static checks — no coupling regressions or blocking issues in the code graph. That is not the same as safe to merge: see what was not checked.

Not checked: tests were not run; formal verification proved 0 of 3 changed function(s) (3 sampled, not proven).

Formal verification. PR-changed functions: 3/3 verified (0 proven, 3 may-equivalent, 0 distinguished) · 0 not verified.


Graphify review — findings

Fixes the source file on cross-repo member-call edges: they now use the file where the call actually happens (e.g. the .m) instead of the caller node's own file (often the .h declaring the method). Previously the call-site line number was paired with the wrong file, so it could point past the end of an unrelated file. _park_unresolved_member_call now records the call-site file on each parked entry, and extract relativizes it like source_file, so absolute checkout paths don't leak into graph.json or the merged edge. Graphs parked before this change have no file, so link_cross_repo_member_calls falls back to the caller's source_file, which is the old behavior. Adds tests for the new edge source_file, the pre-#3152 fallback, and relative-path parking on ObjC. Existing parked-call assertions in the Go, PHP and TS tests now ignore file, since they check shape rather than location.

No blocking issues surfaced. 1 lower-confidence candidate did not survive cross-model review.

Analysis details — impact, health, verification

Impact & health

Graphify review

Impact — 3244 functions depend on the 475 functions this change touches.

Health — this change adds coupling hotspots:

  • worse: extract() — 989 callers, 59 callees
  • worse: link_cross_repo_member_calls() — 34 callers, 10 callees

Verification — 3244 functions in the blast radius were not formally verified this run (proofs are advisory here).

Gate & verification

graphify gate

PASS — objectively clean (no health regressions, tests not run — proofs not run this pass (advisory)). Grounded, not self-assessed.

Advisory (not blocking):

  • verification_scope: 2998 function(s) in the blast radius were not formally verified this run

Test selection

Test selection

206 of 437 test file(s) selected (47%) via static blast radius.

  • tests/test_affected_overrides.py — impact
  • tests/test_astro_extraction.py — impact
  • tests/test_astro_import_ids.py — impact
  • tests/test_blade_extractor.py — impact
  • tests/test_build.py — impact
  • tests/test_builtin_global_type_refs.py — impact
  • tests/test_c_include_resolution.py — impact
  • tests/test_cache.py — impact
  • tests/test_case_sensitive_resolution.py — impact
  • tests/test_cjs_module_extension.py — impact
  • tests/test_cobol_extractor.py — impact
  • tests/test_cpp_method_declarations.py — impact
  • tests/test_cpp_nested_and_cli.py — impact
  • tests/test_cpp_objc_cross_file_calls.py — impact
  • tests/test_cpp_template_type_params.py — impact
  • tests/test_cross_extension_reexport_self_cycle.py — impact
  • tests/test_cross_language_call_resolution.py — impact
  • tests/test_cross_repo_external_call_guards.py — impact
  • tests/test_cross_repo_member_calls.py — impact, changed-test
  • tests/test_csharp_call_site_generic_args.py — impact
  • tests/test_csharp_delegate_declarations.py — impact
  • tests/test_csharp_enum_members.py — impact
  • tests/test_csharp_field_generic_args.py — impact
  • tests/test_csharp_foreach_loop_variable.py — impact
  • tests/test_csharp_generic_callsites.py — impact
  • tests/test_csharp_interface_dispatch.py — impact
  • tests/test_csharp_member_calls.py — impact
  • tests/test_csharp_member_chain_calls.py — impact
  • tests/test_csharp_member_nodes.py — impact
  • tests/test_csharp_object_creation.py — impact
  • tests/test_csharp_partial_classes.py — impact
  • tests/test_csharp_tuple_type_refs.py — impact
  • tests/test_csharp_type_resolution.py — impact
  • tests/test_csharp_underscore_collisions.py — impact
  • tests/test_csharp_var_call_return_type.py — impact
  • tests/test_csharp_verbatim_interpolation.py — impact
  • tests/test_definition_file_portability.py — impact
  • tests/test_detect.py — impact
  • tests/test_dotnet.py — impact
  • tests/test_duplicate_annotation_edges.py — impact
  • tests/test_ejs_extractor.py — impact
  • tests/test_elixir_defdelegate.py — impact
  • tests/test_elixir_import_resolution.py — impact
  • tests/test_elixir_keyword_def_calls.py — impact
  • tests/test_elixir_qualified_calls.py — impact
  • tests/test_elixir_unqualified_call_scope.py — impact
  • tests/test_erlang_extractor.py — impact
  • tests/test_export_direction.py — impact
  • tests/test_ext_tagged_id_clash.py — impact
  • tests/test_extract.py — impact
  • … and 156 more

Selection is safe under the controlled-regression assumption; always-run tests + a periodic full run are the backstops. Advisory — it never changes the check verdict.

Formal verification

No difference found (not proven): No behavior difference found in link\_cross\_repo\_member\_calls (not a proof).

The verifier ran both versions of link\_cross\_repo\_member\_calls on many inputs and saw identical behavior every time. Strong evidence the change is safe, but evidence, not a proof.

Guarantee: Empirical: differential testing (both versions run on many generated inputs). A divergence on an untested input remains possible, so this is 'no counterexample found', not 'proven equivalent'.

Note: An input the sampler did not try could still differ.

No difference found (not proven): No behavior difference found in \_park\_unresolved\_member\_call (not a proof).

The verifier ran both versions of \_park\_unresolved\_member\_call on many inputs and saw identical behavior every time. Strong evidence the change is safe, but evidence, not a proof.

Guarantee: Empirical: differential testing (both versions run on many generated inputs). A divergence on an untested input remains possible, so this is 'no counterexample found', not 'proven equivalent'.

Note: An input the sampler did not try could still differ.

No difference found (not proven): No behavior difference found in extract (not a proof).

The verifier ran both versions of extract on many inputs and saw identical behavior every time. Strong evidence the change is safe, but evidence, not a proof.

Guarantee: Empirical: differential testing (both versions run on many generated inputs). A divergence on an untested input remains possible, so this is 'no counterexample found', not 'proven equivalent'.

Note: An input the sampler did not try could still differ.

· 2 more finding(s) on lines outside this diff (see the check run).

This branch has not been deployed

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

Labels

contributor Pull request from a returning community contributor

Projects

None yet

Development

Successfully merging this pull request may close these issues.

cross_repo_calls: edge source_file is the caller node's file (the .h) while source_location is the call-site line (in the .m)

1 participant