mirror of
https://github.com/safishamsi/graphify.git
synced 2026-07-13 02:47:00 +00:00
fix(csharp): emit type references for properties
The C# class-body walker only handled field_declaration, so a
property's type produced no references(field) edge. In idiomatic C#,
auto-properties (`public Widget Main { get; set; }`) — not bare fields
— are the standard way to declare state, so this silently dropped most
of a class's type relationships.
Add a property_declaration branch alongside the field_declaration
handler, guarded the same way (ts_module == tree_sitter_c_sharp,
parent_class_nid set). A property exposes its type on the node directly
(no variable_declaration wrapper), so read it via
child_by_field_name("type") and collect refs with
_csharp_collect_type_refs, mirroring the Java/PHP/Kotlin siblings so
List<Widget> yields both the List field ref and the Widget generic_arg
ref. Only emit when target != parent_class_nid.
This commit is contained in:
@@ -3786,6 +3786,35 @@ def _extract_generic(
|
||||
"references", line, context="field", metadata=metadata)
|
||||
return
|
||||
|
||||
if (config.ts_module == "tree_sitter_c_sharp"
|
||||
and t == "property_declaration"
|
||||
and parent_class_nid):
|
||||
# C# auto-properties (`public Widget Main { get; set; }`) are the
|
||||
# idiomatic way to declare state, yet only field_declaration was
|
||||
# handled — so property types produced no references edge. Unlike a
|
||||
# field, a property exposes its type on the node directly (no
|
||||
# variable_declaration wrapper), so read it straight off the `type`
|
||||
# field. Use _csharp_collect_type_refs (like the Java/PHP/Kotlin
|
||||
# siblings) so `List<Widget>` yields both the List field ref and the
|
||||
# Widget generic_arg ref.
|
||||
type_node = node.child_by_field_name("type")
|
||||
if type_node is not None:
|
||||
line = node.start_point[0] + 1
|
||||
refs: list[tuple[str, str, bool, str]] = []
|
||||
_csharp_collect_type_refs(type_node, source, False, refs)
|
||||
for ref_name, role, qualified, qualifier in refs:
|
||||
ctx = "generic_arg" if role == "generic_arg" else "field"
|
||||
target_nid = ensure_named_node(ref_name, line)
|
||||
if target_nid != parent_class_nid:
|
||||
metadata = {"ref_token": ref_name}
|
||||
if qualified:
|
||||
metadata["qualified"] = True
|
||||
if qualifier:
|
||||
metadata["ref_qualifier"] = qualifier
|
||||
add_edge(parent_class_nid, target_nid, "references",
|
||||
line, context=ctx, metadata=metadata)
|
||||
return
|
||||
|
||||
if (config.ts_module == "tree_sitter_java"
|
||||
and t == "field_declaration"
|
||||
and parent_class_nid):
|
||||
|
||||
Vendored
+4
@@ -21,6 +21,10 @@ namespace GraphifyDemo
|
||||
{
|
||||
private readonly HttpClient _client;
|
||||
|
||||
public Processor Owner { get; set; }
|
||||
|
||||
public List<Processor> Workers { get; set; }
|
||||
|
||||
public DataProcessor()
|
||||
{
|
||||
_client = new HttpClient();
|
||||
|
||||
@@ -542,6 +542,17 @@ def test_csharp_field_type_references_have_field_context():
|
||||
), "DataProcessor field declarations should reference HttpClient with field context"
|
||||
|
||||
|
||||
def test_csharp_property_type_references_have_field_context():
|
||||
r = extract_csharp(FIXTURES / "sample.cs")
|
||||
field_refs = _edge_labels(r, "references", "field")
|
||||
# `public Processor Owner { get; set; }` — property type -> field ref.
|
||||
assert ("DataProcessor", "Processor") in field_refs
|
||||
# `public List<Processor> Workers { get; set; }` — the List container -> field.
|
||||
assert ("DataProcessor", "List") in field_refs
|
||||
# ...and the generic argument -> generic_arg.
|
||||
assert ("DataProcessor", "Processor") in _edge_labels(r, "references", "generic_arg")
|
||||
|
||||
|
||||
def test_csharp_call_edges_have_call_context():
|
||||
r = extract_csharp(FIXTURES / "sample.cs")
|
||||
node_by_id = {n["id"]: n["label"] for n in r["nodes"]}
|
||||
|
||||
Reference in New Issue
Block a user