mirror of
https://github.com/safishamsi/graphify.git
synced 2026-10-13 15:40:05 +00:00
Drop edges of a JS node dropped for colliding with a PHP node
A reviewer on this PR pointed out that when a JS symbol's id collides with an existing PHP node (same name, one file, resolved in favor of the PHP node), the merge still appended every JS edge unconditionally. An edge meant for the discarded JS symbol silently attached to the unrelated PHP node sharing its id instead of vanishing with it. The file node's own always on collision (both passes deliberately reuse its id) is excluded from this so an unrelated JS symbol's own edges sourced from the file node are unaffected. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
ead045be11
commit
c96169b320
1 file changed
+23
-4
+23
-4
@@ -2593,7 +2593,9 @@ def extract_php(path: Path) -> dict:
|
||||
file node id, so JS symbols land under the one file node like any other
|
||||
PHP symbol; a same-name PHP/JS collision (rare — different languages,
|
||||
same file) is resolved by keeping the PHP node, since PHP is the file's
|
||||
primary language.
|
||||
primary language, and dropping every JS edge that touches the id the
|
||||
dropped JS node would have used, so no edge from the discarded symbol
|
||||
is left to silently attach to the unrelated PHP node sharing its id.
|
||||
"""
|
||||
result = _extract_generic(path, _PHP_CONFIG)
|
||||
try:
|
||||
@@ -2602,12 +2604,29 @@ def extract_php(path: Path) -> dict:
|
||||
if not had_script:
|
||||
return result
|
||||
js_result = _extract_generic(path, _JS_CONFIG, source_override=masked.encode("utf-8"))
|
||||
# The file node itself always collides by construction -- both passes
|
||||
# derive its id from the same path, on purpose, so JS symbols can
|
||||
# land under the one PHP file node. That expected collision must not
|
||||
# be treated as a dropped-symbol collision below, or every JS edge
|
||||
# sourced from the file node (i.e. every top-level JS symbol's own
|
||||
# `contains` edge) would be discarded along with it.
|
||||
file_node_id = result["nodes"][0]["id"] if result.get("nodes") else None
|
||||
existing_ids = {n["id"] for n in result.get("nodes", [])}
|
||||
colliding_ids: set = set()
|
||||
for n in js_result.get("nodes", []):
|
||||
if n["id"] not in existing_ids:
|
||||
result.setdefault("nodes", []).append(n)
|
||||
existing_ids.add(n["id"])
|
||||
if n["id"] in existing_ids:
|
||||
if n["id"] != file_node_id:
|
||||
colliding_ids.add(n["id"])
|
||||
continue
|
||||
result.setdefault("nodes", []).append(n)
|
||||
existing_ids.add(n["id"])
|
||||
for e in js_result.get("edges", []):
|
||||
# A JS node dropped above for colliding with an existing PHP
|
||||
# node id must not leave its edges behind -- otherwise an edge
|
||||
# meant for the dropped JS symbol silently attaches to the
|
||||
# unrelated retained PHP node that happens to share its id.
|
||||
if e.get("source") in colliding_ids or e.get("target") in colliding_ids:
|
||||
continue
|
||||
result.setdefault("edges", []).append(e)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
Reference in new issue
Block a user