Repository navigation
Conversation
…s#4206) Co-Authored-By: Grok Bot <noreply@x.ai>
|
Thanks for the pull request, @Mpasha17. 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. |
There was a problem hiding this comment.
Graphify reviewed this change.
Worth a look — the grounded gate found no coupling regressions or blocking issues, but 1 advisory finding(s) below merit a look before merge.
Formal verification. PR-changed functions: 1/1 verified (0 proven, 1 may-equivalent, 0 distinguished) · 0 not verified.
Graphify review — findings
Adds cross-file calls edges for Elixir module-qualified calls like Accounts.get_user(id): extract_elixir now expands the receiver through alias tables (including as:, function-local aliases, nested-module auto-aliases, and __MODULE__) and links same-file targets directly. Everything else goes to the new _resolve_elixir_qualified_calls pass, which only adds an edge when the module matches exactly one top-level corpus module that defines the function. External modules like Repo or Enum get no edge rather than a same-named guess.
Worth a look
defmodule __MODULE__.Childis registered under an unexpandable name —graphify/extractors/elixir.py:163· Escalate · medium- agreed by 2 of 2 members but NOT verified (no proof, no reproducing execution) — consensus is not a verdict; needs human review
Analysis details — impact, health, verification
Impact & health
Graphify review
Impact — 2543 functions depend on the 313 functions this change touches.
Health — this change adds coupling hotspots:
- new:
extract()— 800 callers, 51 callees - new:
_rebuild_code()— 160 callers, 56 callees - new:
extract_js()— 87 callers, 5 callees - new:
extract_xaml()— 19 callers, 17 callees - new:
main()— 102 callers, 3 callees - new:
dispatch_command()— 2 callers, 129 callees - new:
extract_cpp()— 36 callers, 5 callees - new:
_get_extractor()— 27 callers, 6 callees - …and 42 more — each is listed as a finding
Verification — 2543 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: 2348 function(s) in the blast radius were not formally verified this run
Test selection
Test selection
153 of 345 test file(s) selected (44%) via static blast radius.
tests/test_astro_extraction.py— impacttests/test_astro_import_ids.py— impacttests/test_blade_extractor.py— impacttests/test_build.py— impacttests/test_builtin_global_type_refs.py— impacttests/test_cache.py— impacttests/test_case_sensitive_resolution.py— impacttests/test_cjs_module_extension.py— impacttests/test_cobol_extractor.py— impacttests/test_cpp_method_declarations.py— impacttests/test_cpp_nested_and_cli.py— impacttests/test_cpp_objc_cross_file_calls.py— impacttests/test_cross_extension_reexport_self_cycle.py— impacttests/test_cross_language_call_resolution.py— impacttests/test_cross_repo_external_call_guards.py— impacttests/test_cross_repo_member_calls.py— impacttests/test_csharp_call_site_generic_args.py— impacttests/test_csharp_enum_members.py— impacttests/test_csharp_field_generic_args.py— impacttests/test_csharp_generic_callsites.py— impacttests/test_csharp_interface_dispatch.py— impacttests/test_csharp_member_calls.py— impacttests/test_csharp_member_nodes.py— impacttests/test_csharp_object_creation.py— impacttests/test_csharp_partial_classes.py— impacttests/test_csharp_tuple_type_refs.py— impacttests/test_csharp_type_resolution.py— impacttests/test_definition_file_portability.py— impacttests/test_detect.py— impacttests/test_dotnet.py— impacttests/test_duplicate_annotation_edges.py— impacttests/test_elixir_import_resolution.py— impacttests/test_elixir_qualified_calls.py— impact, changed-testtests/test_elixir_unqualified_call_scope.py— impacttests/test_erlang_extractor.py— impacttests/test_extract.py— impacttests/test_extract_cache_location.py— impacttests/test_extract_path_memo.py— impacttests/test_extract_php_closures.py— impacttests/test_file_label_disambiguation.py— impacttests/test_file_node_id_spec.py— impacttests/test_forwarding_review_findings.py— impacttests/test_go_builtin_call_targets.py— impacttests/test_go_import_repoint.py— impacttests/test_go_interface_methods.py— impacttests/test_go_qualified_resolution.py— impacttests/test_import_extension_resolution.py— impacttests/test_import_self_loops.py— impacttests/test_imported_export_forwarding.py— impacttests/test_incremental.py— impact- … and 103 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.
Docs that may be stale (advisory)
ARCHITECTURE.md§ Extraction output schema (lines 50-66): references changed symbolscalls,nameARCHITECTURE.md§ Adding a new language extractor (lines 81-88): references changed symbolscallsBENCHMARKS.md§ INFERRED cross-file edge precision (FastAPI demo corpus) (lines 152-166): references changed symbolscallsCHANGELOG.md§ 0.9.77 (2026-10-05) (lines 45-64): references changed symbolscallsCHANGELOG.md§ 0.9.76 (2026-10-04) (lines 65-83): references changed symbolscalls,nameCHANGELOG.md§ 0.9.75 (2026-10-04) (lines 84-104): references changed symbolscalls,nameCHANGELOG.md§ 0.9.74 (2026-10-02) (lines 105-120): references changed symbolscallsCHANGELOG.md§ 0.9.73 (2026-09-30) (lines 121-136): references changed symbolscallsCHANGELOG.md§ 0.9.70 (2026-09-27) (lines 164-173): references changed symbolscalls,nameCHANGELOG.md§ 0.9.68 (2026-09-25) (lines 185-197): references changed symbolscalls
…and 10 more.
Formal verification
No difference found (not proven): No behavior difference found in extract\_elixir (not a proof).
The verifier ran both versions of extract\_elixir 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.
· 1 grounded finding(s) anchored inline below; 49 more finding(s) on lines outside this diff (see the check run).
|
Checked the |
Closes #4206
The Elixir extractor threw away the module part of a remote call and kept only the function name. So
App.Accounts.get_user(id)andAccounts.get_user(id)(afteralias App.Accounts) got nocallsedge at all, andApp.Repo.insert(x)inside a module with its owninsert/1was linked to that local function as EXTRACTED. The same went forMap.update(...),Enum.map(...),conn.assignsand so on whenever the caller's module had a function with that name.Now
walk_callskeeps the receiver when it's a module name and expands it through the alias table in scope (alias A.B,alias A.B, as: C,alias A.{B, C}, aliases inside a function body, the implicit alias of a nesteddefmodule, and__MODULE__). If that module is in the same file the edge is made right there. Otherwise the call goes to a newelixir_qualified_callsresolver, which links it only when exactly one top-level module in the corpus has that name and that module defines the function. Modules outside the corpus get nothing. A qualified call never goes through the bare-name lookup anymore, and calls on a variable (mod.fun(),conn.assigns,fun.(x)) or an Erlang module (:ets.new) stay unlinked. Unqualified, import/use and local calls work the same as before.Limits: arity isn't checked, so
Mod.fun/1andMod.fun/2both point at thefunnode. A nested module defined in another file (App.Web.Helpersdeclared insideApp.Web) isn't a cross-file target, same as for the existing import-target pass.require A, as: Bisn't treated as an alias, and dynamic receivers likeModule.concat(...)aren't resolved.Testing: new
tests/test_elixir_qualified_calls.pywith 11 tests. 9 of them fail on current v8; the nested-module and import/local control tests pass on both. The full suite on 3.10/3.12/3.13/3.14 shows the same failures as v8. Ruff is clean and pyright shows no new findings. The issue's repro now gives exactly the expected edges, also after an incrementalgraphify update. On hexpm, plausible/analytics and phoenix the Elixircallsedges went from 3464 to 4811, 2892 to 5091 and 1163 to 1439. Nothing outside.ex/.exschanged. I spot-checked a sample of the new edges and they're correct. Every removed edge was a remote or variable call that had been bound to a same-named local function.AI-assisted (Grok Bot); each commit carries a Co-Authored-By line.