probe_code/language/
csharp.rs1use super::language_trait::LanguageImpl;
2use tree_sitter::{Language as TSLanguage, Node};
3
4pub struct CSharpLanguage;
6
7impl Default for CSharpLanguage {
8 fn default() -> Self {
9 Self::new()
10 }
11}
12
13impl CSharpLanguage {
14 pub fn new() -> Self {
15 CSharpLanguage
16 }
17}
18
19impl LanguageImpl for CSharpLanguage {
20 fn get_tree_sitter_language(&self) -> TSLanguage {
21 unsafe { std::mem::transmute(tree_sitter_c_sharp::LANGUAGE) }
23 }
24
25 fn get_extension(&self) -> &'static str {
26 "cs"
27 }
28
29 fn is_acceptable_parent(&self, node: &Node) -> bool {
30 matches!(
31 node.kind(),
32 "method_declaration"
33 | "class_declaration"
34 | "struct_declaration"
35 | "interface_declaration"
36 | "enum_declaration"
37 | "namespace_declaration"
38 | "property_declaration"
39 | "constructor_declaration"
40 | "delegate_declaration"
41 | "event_declaration"
42 )
43 }
44
45 fn is_test_node(&self, node: &Node, source: &[u8]) -> bool {
46 let debug_mode = std::env::var("DEBUG").unwrap_or_default() == "1";
47 let node_type = node.kind();
48
49 if node_type == "method_declaration" {
51 let mut cursor = node.walk();
52
53 let mut has_test_attribute = false;
55
56 for child in node.children(&mut cursor) {
57 if child.kind() == "attribute_list" {
58 let attr_text = child.utf8_text(source).unwrap_or("");
59 if attr_text.contains("[Test")
60 || attr_text.contains("[TestMethod")
61 || attr_text.contains("[Fact")
62 || attr_text.contains("[Theory")
63 {
64 has_test_attribute = true;
65 break;
66 }
67 }
68 }
69
70 if has_test_attribute {
71 if debug_mode {
72 println!("DEBUG: Test node detected (C#): test attribute");
73 }
74 return true;
75 }
76
77 for child in node.children(&mut cursor) {
79 if child.kind() == "identifier" {
80 let name = child.utf8_text(source).unwrap_or("");
81 if name.starts_with("Test") {
82 if debug_mode {
83 println!("DEBUG: Test node detected (C#): Test method");
84 }
85 return true;
86 }
87 }
88 }
89 }
90
91 if node_type == "class_declaration" {
93 let mut cursor = node.walk();
94
95 for child in node.children(&mut cursor) {
97 if child.kind() == "attribute_list" {
98 let attr_text = child.utf8_text(source).unwrap_or("");
99 if attr_text.contains("[TestClass") || attr_text.contains("[TestFixture") {
100 if debug_mode {
101 println!("DEBUG: Test node detected (C#): test class attribute");
102 }
103 return true;
104 }
105 }
106 }
107
108 for child in node.children(&mut cursor) {
110 if child.kind() == "identifier" {
111 let name = child.utf8_text(source).unwrap_or("");
112 if name.ends_with("Tests") || name.ends_with("Test") {
113 if debug_mode {
114 println!(
115 "DEBUG: Test node detected (C#): Test class naming convention"
116 );
117 }
118 return true;
119 }
120 }
121 }
122 }
123
124 false
125 }
126
127 fn find_parent_function<'a>(&self, node: Node<'a>) -> Option<Node<'a>> {
128 let mut current = node;
129
130 while let Some(parent) = current.parent() {
131 if parent.kind() == "method_declaration" {
132 return Some(parent);
133 }
134 current = parent;
135 }
136
137 None
138 }
139}