mirror of
https://github.com/safishamsi/graphify.git
synced 2026-08-26 16:26:42 +00:00
fix(csharp): extract members inside #if preprocessor blocks (#2634)
This commit is contained in:
committed by
safishamsi
parent
bedf32e07c
commit
cd04bf1bf3
@@ -2162,7 +2162,7 @@ def _csharp_extra_walk(node, source: bytes, file_nid: str, stem: str, str_path:
|
||||
nodes: list, edges: list, seen_ids: set, function_bodies: list,
|
||||
parent_class_nid: str | None, add_node_fn, add_edge_fn,
|
||||
walk_fn, namespace_stack: list[str], scope_stack: list[str]) -> bool:
|
||||
"""Handle namespace declarations for C#. Returns True if handled."""
|
||||
"""Handle C# namespaces and transparent class-member wrappers."""
|
||||
if node.type == "namespace_declaration":
|
||||
ns_name = _csharp_namespace_name(node, source)
|
||||
pushed = False
|
||||
@@ -2199,6 +2199,13 @@ def _csharp_extra_walk(node, source: bytes, file_nid: str, stem: str, str_path:
|
||||
add_node_fn(ns_nid, ns_label, line, node_type="namespace", metadata={"kind": "csharp_namespace"})
|
||||
add_edge_fn(file_nid, ns_nid, "contains", line)
|
||||
return True
|
||||
if parent_class_nid and node.type.startswith("preproc_"):
|
||||
# tree-sitter wraps members in #if/#else/#elif directives in preproc_*
|
||||
# nodes. They are conditional containers, not ownership scopes: dropping
|
||||
# parent_class_nid here makes guarded methods look file-level (#2631).
|
||||
for child in node.children:
|
||||
walk_fn(child, parent_class_nid)
|
||||
return True
|
||||
return False
|
||||
|
||||
def _swift_extra_walk(node, source: bytes, file_nid: str, stem: str, str_path: str,
|
||||
|
||||
@@ -519,6 +519,56 @@ def test_xaml_viewmodel_with_non_utf8_codebehind_does_not_crash(tmp_path):
|
||||
assert nodes[edges[0]["target"]]["label"] == "SettingsViewModel"
|
||||
|
||||
|
||||
def test_csharp_members_in_preprocessor_blocks_are_extracted_and_resolved(tmp_path):
|
||||
"""C# preprocessor wrappers must preserve class ownership for members (#2631)."""
|
||||
helper = tmp_path / "Helper.cs"
|
||||
helper.write_text(
|
||||
"""namespace Probe.Lib;
|
||||
public static class Gated
|
||||
{
|
||||
public static void Outside(string a) { }
|
||||
#if NET8_0_OR_GREATER
|
||||
public static void InsideIf(string a) { }
|
||||
#else
|
||||
public static void InsideElse(string a) { }
|
||||
#endif
|
||||
#if DEBUG
|
||||
public static void InsideDebug(string a) { }
|
||||
#endif
|
||||
}
|
||||
"""
|
||||
)
|
||||
caller = tmp_path / "Caller.cs"
|
||||
caller.write_text(
|
||||
"""namespace Probe.Lib;
|
||||
public static class Caller
|
||||
{
|
||||
public static void Drive()
|
||||
{
|
||||
Gated.Outside(\"x\");
|
||||
Gated.InsideIf(\"x\");
|
||||
Gated.InsideDebug(\"x\");
|
||||
}
|
||||
}
|
||||
"""
|
||||
)
|
||||
|
||||
result = extract([helper, caller], cache_root=tmp_path)
|
||||
by_label = {node["label"]: node["id"] for node in result["nodes"]}
|
||||
|
||||
for label in (".Outside()", ".InsideIf()", ".InsideElse()", ".InsideDebug()"):
|
||||
assert label in by_label
|
||||
|
||||
calls = {
|
||||
(edge["source"], edge["target"])
|
||||
for edge in result["edges"]
|
||||
if edge["relation"] == "calls"
|
||||
}
|
||||
assert (by_label[".Drive()"], by_label[".Outside()"]) in calls
|
||||
assert (by_label[".Drive()"], by_label[".InsideIf()"]) in calls
|
||||
assert (by_label[".Drive()"], by_label[".InsideDebug()"]) in calls
|
||||
|
||||
|
||||
# ── .razor ───────────────────────────────────────────────────────────────────
|
||||
|
||||
def test_razor_using_and_inject():
|
||||
|
||||
Reference in New Issue
Block a user