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:
rajatnagda45
2026-08-24 13:16:45 +01:00
committed by safishamsi
parent 46d3e5d5b8
commit be5110a789
2 changed files with 55 additions and 0 deletions
+26
View File
@@ -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:
+29
View File
@@ -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")