test(extract): cover per-symbol fan-out and module-top-level drop for #2652
Adds two regression tests on top of #2684: each referencing symbol gets its own INFERRED uses edge (guarding against the old every-class fan-out and against source collapse), and a true module-top-level reference emits no edge (the deliberate drop). Also adds the CHANGELOG entry. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
c08d9afa93
commit
bd1ede9584
@@ -4,6 +4,7 @@ Full release notes with details on each version: [GitHub Releases](https://githu
|
||||
|
||||
## 0.9.42 (unreleased)
|
||||
|
||||
- Fix: a cross-file INFERRED `uses` edge now binds to the symbol whose body actually references the imported name (a module-level function is a valid source; a co-located class that never touches the import gets no edge), instead of fanning out from the import line to every class in the importing file (#2652, thanks @ousamabenyounes). A reference at module top level, with no enclosing symbol, emits no edge.
|
||||
- Feature: OCaml `.ml`/`.mli` extraction via tree-sitter-ocaml (optional `[ocaml]` extra). Extracts modules, top-level and module-level values/functions, types and their variant constructors, `open` imports, and function calls; qualified calls (`Geo.area`) resolve to the value, and cross-file `open`/call targets collapse onto the unique real definition via the corpus stub rewire.
|
||||
- Fix: a JS/TS `for...of` / `for...in` loop binding is now shadowed, so passing it as a call argument no longer fabricates an `indirect_call` edge to an unrelated same-named callable (#2685, thanks @ousamabenyounes); completes the loop/closure/catch shadow family (#2568/#2569/#2517).
|
||||
- Fix: graph provenance (`built_at_commit`) is stamped from the analysed repository rather than the shell's working directory, so `graphify extract` run from elsewhere records the target's commit, not the caller's (#2534 family; #2699, thanks @C0KERNEL).
|
||||
|
||||
@@ -3494,3 +3494,41 @@ def test_inferred_uses_edge_follows_an_import_alias(tmp_path):
|
||||
result = extract([tmp_path / "api.py", tmp_path / "helpers.py"], cache_root=tmp_path)
|
||||
|
||||
assert ("api_handler", "helpers_helper") in _inferred_uses(result)
|
||||
|
||||
|
||||
def test_inferred_uses_edge_emitted_once_per_referencing_symbol(tmp_path):
|
||||
"""Each symbol that references the import gets its own edge, and only those
|
||||
symbols do — guards against the old fan-out (every class in the file) and
|
||||
against collapsing distinct sources into one (#2652)."""
|
||||
(tmp_path / "helpers.py").write_text("class Helper:\n pass\n", encoding="utf-8")
|
||||
(tmp_path / "api.py").write_text(
|
||||
"from helpers import Helper\n\n\n"
|
||||
"def a(x):\n return Helper()\n\n\n"
|
||||
"def b(x):\n return Helper()\n\n\n"
|
||||
"def c(x):\n return x\n", # references nothing -> no edge
|
||||
encoding="utf-8",
|
||||
)
|
||||
|
||||
result = extract([tmp_path / "api.py", tmp_path / "helpers.py"], cache_root=tmp_path)
|
||||
uses = _inferred_uses(result)
|
||||
|
||||
assert ("api_a", "helpers_helper") in uses
|
||||
assert ("api_b", "helpers_helper") in uses
|
||||
assert ("api_c", "helpers_helper") not in uses
|
||||
|
||||
|
||||
def test_inferred_uses_edge_dropped_for_module_top_level_reference(tmp_path):
|
||||
"""A reference at true module top level has no enclosing symbol to anchor on,
|
||||
so no INFERRED `uses` edge is emitted (rather than falling back to the file
|
||||
node) — the deliberate drop documented for #2652."""
|
||||
(tmp_path / "helpers.py").write_text("class Helper:\n pass\n", encoding="utf-8")
|
||||
(tmp_path / "api.py").write_text(
|
||||
"from helpers import Helper\n\n\n"
|
||||
"SENTINEL = Helper()\n", # top-level, outside any def/class
|
||||
encoding="utf-8",
|
||||
)
|
||||
|
||||
result = extract([tmp_path / "api.py", tmp_path / "helpers.py"], cache_root=tmp_path)
|
||||
uses = _inferred_uses(result)
|
||||
|
||||
assert not any(tgt == "helpers_helper" for _, tgt in uses)
|
||||
|
||||
Reference in New Issue
Block a user