fix(commonlisp): derive node ids from the full path stem

The Common Lisp extractor minted its id prefix from the bare path.stem instead of the
canonical _file_stem used by every other extractor, so two same-basename .lisp files in
different directories collided (one file's nodes vanished on merge) and nested .lisp files
tripped a spurious legacy-id nudge. Use _make_id(_file_stem(path)) to match the shared
convention; cross-file rewire is unaffected (it matches on label, not id).
This commit is contained in:
guitelesc
2026-08-27 20:20:36 +01:00
committed by safishamsi
parent 8d611dc4d0
commit e906227cf6
2 changed files with 28 additions and 2 deletions
+6 -2
View File
@@ -4,7 +4,7 @@ from __future__ import annotations
import warnings
from pathlib import Path
from graphify.extractors.base import _make_id
from graphify.extractors.base import _file_stem, _make_id
# Standard CL definer forms that introduce data/type/variable bindings
@@ -84,7 +84,11 @@ def extract_commonlisp(path: Path) -> dict:
except Exception as e:
return {"nodes": [], "edges": [], "error": str(e)}
stem = path.stem
# Path-qualified, not the bare `path.stem`: same-named .lisp files in
# different directories must not collide (#1504). Pre-collapsed through
# `_make_id` because `_cl_id` would otherwise map the `/` separators to
# `_slash` via _CL_CHAR_MAP.
stem = _make_id(_file_stem(path))
str_path = str(path)
nodes: list[dict] = []
edges: list[dict] = []
+22
View File
@@ -3974,3 +3974,25 @@ def test_zig_enum_and_union_methods_are_extracted(tmp_path):
for e in r["edges"] if e["relation"] == "calls"
}
assert (".area()", "helper()") in calls, "call from union method body dropped"
@_needs_commonlisp
def test_cl_ids_are_path_qualified_across_directories(tmp_path):
"""Two same-named .lisp files in DIFFERENT directories must mint distinct
ids (#1504). The prefix was derived from the bare `path.stem`, so both
`a/sample.lisp` and `b/sample.lisp` minted `sample` / `sample_init`; when
they land in separate extract batches (what `graphify update` does) build()
merges them and one file's nodes are dropped."""
a = tmp_path / "a" / "sample.lisp"
b = tmp_path / "b" / "sample.lisp"
for p in (a, b):
p.parent.mkdir(parents=True)
p.write_text("(defun init (x) (+ x 1))\n")
ids_a = {n["id"] for n in extract_commonlisp(a)["nodes"]}
ids_b = {n["id"] for n in extract_commonlisp(b)["nodes"]}
assert not (ids_a & ids_b), (
f"same-named .lisp files in different dirs must not share ids, "
f"got overlap {sorted(ids_a & ids_b)}"
)