qex_core/chunk/languages/
csharp.rs1use super::{extract_preceding_comments, find_child_text, find_name, NodeMetadata, LanguageChunker};
2use crate::chunk::ChunkType;
3
4pub struct CSharpChunker;
5
6impl LanguageChunker for CSharpChunker {
7 fn tree_sitter_language(&self) -> tree_sitter::Language {
8 tree_sitter_c_sharp::LANGUAGE.into()
9 }
10
11 fn language_name(&self) -> &str {
12 "csharp"
13 }
14
15 fn file_extensions(&self) -> &[&str] {
16 &["cs"]
17 }
18
19 fn is_splittable(&self, node_type: &str) -> bool {
20 matches!(
21 node_type,
22 "method_declaration"
23 | "class_declaration"
24 | "interface_declaration"
25 | "struct_declaration"
26 | "enum_declaration"
27 | "namespace_declaration"
28 | "constructor_declaration"
29 | "property_declaration"
30 )
31 }
32
33 fn has_nested_chunks(&self, node_type: &str) -> bool {
34 matches!(
35 node_type,
36 "class_declaration"
37 | "interface_declaration"
38 | "struct_declaration"
39 | "namespace_declaration"
40 )
41 }
42
43 fn classify_node(&self, node_type: &str, parent_name: Option<&str>) -> ChunkType {
44 match node_type {
45 "class_declaration" => ChunkType::Class,
46 "interface_declaration" => ChunkType::Interface,
47 "struct_declaration" => ChunkType::Struct,
48 "enum_declaration" => ChunkType::Enum,
49 "namespace_declaration" => ChunkType::Namespace,
50 "method_declaration" | "constructor_declaration" | "property_declaration" => {
51 if parent_name.is_some() {
52 ChunkType::Method
53 } else {
54 ChunkType::Function
55 }
56 }
57 _ => ChunkType::ModuleLevel,
58 }
59 }
60
61 fn extract_metadata(&self, node: tree_sitter::Node, source: &str) -> NodeMetadata {
62 let mut meta = NodeMetadata::default();
63
64 match node.kind() {
65 "method_declaration" | "constructor_declaration" | "property_declaration" => {
66 meta.name = find_name(node, source);
67 meta.docstring = extract_preceding_comments(node, source);
68 if let Some(prev) = node.prev_sibling() {
70 if prev.kind() == "attribute_list" {
71 let text = &source[prev.start_byte()..prev.end_byte()];
72 meta.decorators.push(text.to_string());
73 }
74 }
75 let text = &source[node.start_byte()..node.end_byte()];
76 meta.is_async = text.contains("async ");
77 }
78 "class_declaration" | "interface_declaration" | "struct_declaration"
79 | "enum_declaration" => {
80 meta.name = find_name(node, source);
81 meta.docstring = extract_preceding_comments(node, source);
82 }
83 "namespace_declaration" => {
84 meta.name = find_name(node, source)
85 .or_else(|| find_child_text(node, source, "qualified_name"));
86 meta.docstring = extract_preceding_comments(node, source);
87 }
88 _ => {
89 meta.name = find_name(node, source);
90 meta.docstring = extract_preceding_comments(node, source);
91 }
92 }
93
94 meta
95 }
96}