qex_core/chunk/languages/
cpp.rs1use super::{extract_preceding_comments, find_child_text, find_name, NodeMetadata, LanguageChunker};
2use crate::chunk::ChunkType;
3
4pub struct CppChunker;
5
6impl LanguageChunker for CppChunker {
7 fn tree_sitter_language(&self) -> tree_sitter::Language {
8 tree_sitter_cpp::LANGUAGE.into()
9 }
10
11 fn language_name(&self) -> &str {
12 "cpp"
13 }
14
15 fn file_extensions(&self) -> &[&str] {
16 &["cpp", "cc", "cxx", "hpp", "hh", "hxx"]
17 }
18
19 fn is_splittable(&self, node_type: &str) -> bool {
20 matches!(
21 node_type,
22 "function_definition"
23 | "class_specifier"
24 | "struct_specifier"
25 | "enum_specifier"
26 | "namespace_definition"
27 | "template_declaration"
28 )
29 }
30
31 fn has_nested_chunks(&self, node_type: &str) -> bool {
32 matches!(
33 node_type,
34 "class_specifier" | "struct_specifier" | "namespace_definition" | "template_declaration"
35 )
36 }
37
38 fn classify_node(&self, node_type: &str, parent_name: Option<&str>) -> ChunkType {
39 match node_type {
40 "class_specifier" => ChunkType::Class,
41 "struct_specifier" => ChunkType::Struct,
42 "enum_specifier" => ChunkType::Enum,
43 "namespace_definition" => ChunkType::Namespace,
44 "function_definition" if parent_name.is_some() => ChunkType::Method,
45 "function_definition" => ChunkType::Function,
46 "template_declaration" => ChunkType::Function,
47 _ => ChunkType::ModuleLevel,
48 }
49 }
50
51 fn extract_metadata(&self, node: tree_sitter::Node, source: &str) -> NodeMetadata {
52 let mut meta = NodeMetadata::default();
53
54 match node.kind() {
55 "function_definition" => {
56 let mut cursor = node.walk();
57 for child in node.children(&mut cursor) {
58 if child.kind() == "function_declarator" {
59 meta.name = find_name(child, source)
60 .or_else(|| find_child_text(child, source, "field_identifier"))
61 .or_else(|| find_child_text(child, source, "destructor_name"));
62 }
63 }
64 meta.docstring = extract_preceding_comments(node, source);
65 }
66 "class_specifier" | "struct_specifier" | "enum_specifier" => {
67 meta.name = find_child_text(node, source, "type_identifier")
68 .or_else(|| find_name(node, source));
69 meta.docstring = extract_preceding_comments(node, source);
70 }
71 "namespace_definition" => {
72 meta.name = find_name(node, source);
73 meta.docstring = extract_preceding_comments(node, source);
74 }
75 "template_declaration" => {
76 let mut cursor = node.walk();
78 for child in node.children(&mut cursor) {
79 if child.kind() == "function_definition" || child.kind() == "class_specifier" {
80 let inner = self.extract_metadata(child, source);
81 meta.name = inner.name;
82 meta.docstring = inner.docstring;
83 break;
84 }
85 }
86 if meta.docstring.is_none() {
87 meta.docstring = extract_preceding_comments(node, source);
88 }
89 }
90 _ => {
91 meta.name = find_name(node, source);
92 meta.docstring = extract_preceding_comments(node, source);
93 }
94 }
95
96 meta
97 }
98}