mirror of
https://github.com/safishamsi/graphify.git
synced 2026-10-14 07:59:40 +00:00
fix(powershell): link enum members with case_of instead of contains
A PowerShell enum member is a discriminant case, not a declared field, so it
should hang off its enum with a case_of edge like every other language that
has enums (Java #1719, C#, Swift, Rust, VB.NET). PowerShell was routing enum
members through the same contains path used for class members.
The relation is not cosmetic: case_of targets are excluded from constructor
binding, so an enum member named like a type could previously be mistaken for
one.
Update the existing enum test to expect case_of and add a focused regression
test asserting enum members get case_of (and not contains) while the file
still contains the enum type via contains.
(cherry picked from commit 011dda9b0f)
This commit is contained in:
1 parent
4f0eb679bf
commit
282e2bbc56
2 files changed
+36
-5
No files matched your search
@@ -150,7 +150,13 @@ def extract_powershell(path: Path) -> dict:
|
||||
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)
|
||||
# An enum member is a discriminant case, not a declared
|
||||
# field, so it gets `case_of` like every other language with
|
||||
# enums (Java #1719, C#, Swift, Rust, VB.NET). The relation
|
||||
# also matters to resolution: `case_of` targets are excluded
|
||||
# from constructor binding, so an enum member named like a
|
||||
# type can no longer be mistaken for one.
|
||||
add_edge(enum_nid, member_nid, "case_of", m_line)
|
||||
return
|
||||
|
||||
if t == "class_statement":
|
||||
|
||||
+29
-4
@@ -2699,19 +2699,44 @@ def test_powershell_enum_is_extracted_and_reference_resolves(tmp_path):
|
||||
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 = {
|
||||
# members are captured, hanging off the enum via case_of (not contains)
|
||||
cases = {
|
||||
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"]
|
||||
if e["relation"] == "case_of" and e["source"] == color["id"] and e["target"] == n["id"]
|
||||
}
|
||||
assert {"Red", "Green", "Blue"} <= contained, f"enum members missing: {contained}"
|
||||
assert {"Red", "Green", "Blue"} <= cases, f"enum members missing: {cases}"
|
||||
# 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_enum_members_emit_case_of_not_contains(tmp_path):
|
||||
"""A PowerShell enum member is a discriminant case, so it must get a
|
||||
`case_of` edge like every other language with enums (Java #1719, C#, Swift,
|
||||
Rust, VB.NET), not the `contains` edge used for real class fields.
|
||||
PowerShell was routing enum members through the same `contains` path as a
|
||||
class property. The relation also matters to resolution: `case_of` targets
|
||||
are excluded from constructor binding, so an enum member named like a type
|
||||
can no longer be mistaken for one.
|
||||
"""
|
||||
f = tmp_path / "status.ps1"
|
||||
f.write_text("enum Status {\n Active\n Paused\n Closed\n}\n")
|
||||
r = extract_powershell(f)
|
||||
case_of = _edge_labels(r, "case_of")
|
||||
contains = _edge_labels(r, "contains")
|
||||
# Each enum member hangs off its enum via case_of, not contains.
|
||||
assert ("Status", "Active") in case_of
|
||||
assert ("Status", "Paused") in case_of
|
||||
assert ("Status", "Closed") in case_of
|
||||
assert ("Status", "Active") not in contains
|
||||
# Containment itself (the file owning the enum type) still uses `contains`;
|
||||
# only the member-to-enum relation changed.
|
||||
assert ("status.ps1", "Status") in contains
|
||||
assert ("status.ps1", "Status") not in case_of
|
||||
|
||||
|
||||
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