mirror of
https://github.com/safishamsi/graphify.git
synced 2026-09-21 13:05:41 +00:00
fix(rust): emit references edges for enum variant field types
Enum variant payload types were silently dropped — `struct_item` and
`trait_item` had type-reference handlers but `enum_item` had none, so the
variant field types were never traversed.
Add an `enum_item` branch that walks
`enum_variant_list -> enum_variant -> ordered_field_declaration_list`
(tuple variants, `Click(Logger)`) and `field_declaration_list` (struct
variants, `Resize { size: Dim }`), emitting a `references` edge from the enum
to each field type. Reuses the same type collection as the struct path. Adds
an enum to the fixture and a regression test.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
committed by
safishamsi
co-authored by
Claude Opus 4.8
parent
b8f41c77eb
commit
674184d462
@@ -8160,6 +8160,45 @@ def extract_rust(path: Path) -> dict:
|
||||
if tgt != item_nid:
|
||||
add_edge(item_nid, tgt, "references",
|
||||
field.start_point[0] + 1, context=ctx)
|
||||
if t == "enum_item":
|
||||
# Variant payload types nest under enum_variant_list ->
|
||||
# enum_variant -> ordered_field_declaration_list (tuple variant,
|
||||
# `Click(Logger)`) | field_declaration_list (struct variant,
|
||||
# `Resize { size: Dim }`). Neither was traversed, so every
|
||||
# enum-variant type reference was silently dropped.
|
||||
_TYPE_NODES = ("type_identifier", "generic_type",
|
||||
"scoped_type_identifier", "reference_type",
|
||||
"primitive_type", "tuple_type", "array_type")
|
||||
|
||||
def _emit_enum_type(type_node, at_line):
|
||||
if type_node is None:
|
||||
return
|
||||
refs2: list[tuple[str, str]] = []
|
||||
_rust_collect_type_refs(type_node, source, False, refs2)
|
||||
for ref_name, role in refs2:
|
||||
ctx = "generic_arg" if role == "generic_arg" else "field"
|
||||
tgt = ensure_named_node(ref_name, at_line)
|
||||
if tgt != item_nid:
|
||||
add_edge(item_nid, tgt, "references", at_line, context=ctx)
|
||||
|
||||
for c in node.children:
|
||||
if c.type != "enum_variant_list":
|
||||
continue
|
||||
for variant in c.children:
|
||||
if variant.type != "enum_variant":
|
||||
continue
|
||||
vline = variant.start_point[0] + 1
|
||||
for vc in variant.children:
|
||||
if vc.type == "ordered_field_declaration_list":
|
||||
for tc in vc.children:
|
||||
if tc.type in _TYPE_NODES:
|
||||
_emit_enum_type(tc, vline)
|
||||
elif vc.type == "field_declaration_list":
|
||||
for field in vc.children:
|
||||
if field.type != "field_declaration":
|
||||
continue
|
||||
type_node = field.child_by_field_name("type")
|
||||
_emit_enum_type(type_node, field.start_point[0] + 1)
|
||||
return
|
||||
|
||||
if t == "impl_item":
|
||||
|
||||
Vendored
+5
@@ -51,3 +51,8 @@ impl DataProcessor {
|
||||
Result { value: input }
|
||||
}
|
||||
}
|
||||
|
||||
enum GraphEvent {
|
||||
NodeAdded(Graph),
|
||||
Processed { proc: DataProcessor },
|
||||
}
|
||||
|
||||
@@ -346,6 +346,19 @@ def test_rust_supertrait_emits_inherits():
|
||||
assert ("Logger", "Processor") in _edge_labels(r, "inherits")
|
||||
|
||||
|
||||
def test_rust_enum_variant_references():
|
||||
"""Enum variant payload types must emit `references` edges.
|
||||
|
||||
Tuple variants (`Click(T)`) and struct variants (`Resize { x: T }`) nest
|
||||
their field types under enum_variant_list -> enum_variant; that path was
|
||||
never traversed, so every enum-variant type reference was dropped.
|
||||
"""
|
||||
r = extract_rust(FIXTURES / "sample.rs")
|
||||
refs = _edge_labels(r, "references")
|
||||
assert ("GraphEvent", "Graph") in refs, "tuple-variant reference missing"
|
||||
assert ("GraphEvent", "DataProcessor") in refs, "struct-variant reference missing"
|
||||
|
||||
|
||||
def test_rust_struct_field_emits_field_context():
|
||||
r = extract_rust(FIXTURES / "sample.rs")
|
||||
assert ("DataProcessor", "Result") in _edge_labels(r, "references", "field")
|
||||
|
||||
Reference in New Issue
Block a user