mirror of
https://github.com/safishamsi/graphify.git
synced 2026-08-28 17:26:48 +00:00
fix(powershell): extract enum definitions and their members
A PowerShell enum definition and its members were not extracted, so a [Color] type reference resolved to a sourceless phantom stub instead of the real enum. Emit the enum as a real sourced node with its members as contained children (mirroring class_statement), so references resolve to it; no builtins are fabricated.
This commit is contained in:
@@ -127,6 +127,32 @@ def extract_powershell(path: Path) -> dict:
|
||||
walk(body, parent_class_nid)
|
||||
return
|
||||
|
||||
if t == "enum_statement":
|
||||
# PowerShell enums are first-class type definitions (referenced via
|
||||
# `[Color]` type literals) but were not extracted at all, so those
|
||||
# references resolved to a sourceless phantom stub instead of the real
|
||||
# in-file definition — and the enum's members were lost entirely.
|
||||
name_node = next((c for c in node.children if c.type == "simple_name"), None)
|
||||
if name_node:
|
||||
enum_name = _read_text(name_node, source)
|
||||
line = node.start_point[0] + 1
|
||||
enum_nid = _make_id(stem, enum_name)
|
||||
add_node(enum_nid, enum_name, line)
|
||||
add_edge(file_nid, enum_nid, "contains", line)
|
||||
for member in node.children:
|
||||
if member.type != "enum_member":
|
||||
continue
|
||||
mname_node = next(
|
||||
(c for c in member.children if c.type == "simple_name"), None)
|
||||
if mname_node is None:
|
||||
continue
|
||||
member_name = _read_text(mname_node, source)
|
||||
m_line = member.start_point[0] + 1
|
||||
member_nid = _make_id(enum_nid, member_name)
|
||||
add_node(member_nid, member_name, m_line)
|
||||
add_edge(enum_nid, member_nid, "contains", m_line)
|
||||
return
|
||||
|
||||
if t == "class_statement":
|
||||
name_node = next((c for c in node.children if c.type == "simple_name"), None)
|
||||
if name_node:
|
||||
|
||||
@@ -2065,6 +2065,35 @@ def test_powershell_class_base_type_emits_inherits_edge():
|
||||
assert ("Circle", "Shape") in _edge_labels(r, "inherits")
|
||||
|
||||
|
||||
def test_powershell_enum_is_extracted_and_reference_resolves(tmp_path):
|
||||
"""A PowerShell enum must be a real definition, and `[Enum]` refs resolve to it.
|
||||
|
||||
Enums were not extracted at all, so `[Color]$c` produced a `references` edge to
|
||||
a sourceless phantom stub instead of the enum, and the enum's members were lost.
|
||||
"""
|
||||
f = tmp_path / "colors.ps1"
|
||||
f.write_text(
|
||||
"enum Color {\n Red\n Green = 5\n Blue\n}\n\n"
|
||||
"class Widget {\n [Color]$color\n}\n"
|
||||
)
|
||||
r = extract_powershell(f)
|
||||
assert "error" not in r
|
||||
color = next((n for n in r["nodes"] if n["label"] == "Color"), None)
|
||||
assert color is not None, "enum definition dropped"
|
||||
assert color["source_file"] != "", "enum must be a real sourced definition, not a phantom stub"
|
||||
# members are captured
|
||||
contained = {
|
||||
n["label"] for n in r["nodes"]
|
||||
for e in r["edges"]
|
||||
if e["relation"] == "contains" and e["source"] == color["id"] and e["target"] == n["id"]
|
||||
}
|
||||
assert {"Red", "Green", "Blue"} <= contained, f"enum members missing: {contained}"
|
||||
# the field type reference resolves to the real enum node
|
||||
ref_targets = {e["target"] for e in r["edges"]
|
||||
if e["relation"] == "references" and e.get("context") == "field"}
|
||||
assert color["id"] in ref_targets, "[Color] field reference did not resolve to the enum"
|
||||
|
||||
|
||||
def test_powershell_property_field_type_context():
|
||||
r = extract_powershell(FIXTURES / "sample.ps1")
|
||||
assert ("DataProcessor", "string") in _edge_labels(r, "references", "field")
|
||||
|
||||
Reference in New Issue
Block a user