fix(rust): emit a node per enum variant with a case_of edge

The enum_item handler walked each variant only to collect its payload type
references (`Click(Logger)` -> Logger), but never emitted a node for the
variant itself. So an `enum Shape { Circle, Square, Empty }` produced a node
for Shape with no members at all — the enum was a leaf and its variants were
absent from the graph.

Emit a node plus a `case_of` edge per enum_variant, keyed on the variant's
`identifier` child, alongside the existing payload-type walk. This brings
Rust to parity with every other language that has enums: Java's enum_constant
(#1719), Kotlin's enum_entry (#1738), Swift, and Scala.
This commit is contained in:
rajatnagda45 committed 2026-09-30 09:25:28 +05:30
1 parent 1cd9a36c0c
commit 13903a8ac3
2 files changed
+36

No files matched your search

+18
View File
@@ -366,6 +366,24 @@ def extract_rust(path: Path) -> dict:
if variant.type != "enum_variant":
continue
vline = variant.start_point[0] + 1
# Emit a node per variant with a case_of edge back to
# the enum. Only the variants' payload types were
# walked before, so the variants themselves (`Circle`,
# `Square`, `Empty`) never became nodes and the enum
# was left a memberless leaf. This is the Rust parity
# of Java #1719 / Kotlin #1738 / Swift / Scala enums.
# The variant name is the enum_variant's `identifier`.
vname_node = next(
(vc for vc in variant.children
if vc.type == "identifier"),
None,
)
if vname_node is not None:
vname = _read_text(vname_node, source)
if vname:
variant_nid = _make_id(item_nid, vname)
add_node(variant_nid, vname, vline)
add_edge(item_nid, variant_nid, "case_of", vline)
for vc in variant.children:
if vc.type == "ordered_field_declaration_list":
for tc in vc.children:
+18
View File
@@ -410,6 +410,24 @@ def test_rust_enum_variant_references():
assert ("GraphEvent", "DataProcessor") in refs, "struct-variant reference missing"
def test_rust_enum_variants_emit_case_of_nodes():
"""Each enum variant must become a node with a `case_of` edge to its enum.
The enum handler only walked variants to collect their payload type
references; the variants themselves (`NodeAdded`, `Processed`) never became
nodes, so the enum was left a memberless leaf. Every other language with
enums (Java #1719, Kotlin #1738, Swift, Scala) emits a node per member with
a `case_of` edge; this brings Rust to parity.
"""
r = extract_rust(FIXTURES / "sample.rs")
labels = {n["label"] for n in r["nodes"]}
assert "NodeAdded" in labels
assert "Processed" in labels
case_of = _edge_labels(r, "case_of")
assert ("GraphEvent", "NodeAdded") in case_of
assert ("GraphEvent", "Processed") in case_of
def test_rust_struct_field_emits_field_context():
r = extract_rust(FIXTURES / "sample.rs")
assert ("DataProcessor", "Result") in _edge_labels(r, "references", "field")