mirror of
https://github.com/safishamsi/graphify.git
synced 2026-10-13 07:29:33 +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>
(cherry picked from commit c96169b320)
This commit is contained in:
1 parent
cc80351872
commit
96e653cc7c
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