Skip to main content

qex_core/chunk/languages/
rust_lang.rs

1use super::{extract_preceding_comments, find_child_text, find_name, NodeMetadata, LanguageChunker};
2use crate::chunk::ChunkType;
3
4pub struct RustChunker;
5
6impl LanguageChunker for RustChunker {
7    fn tree_sitter_language(&self) -> tree_sitter::Language {
8        tree_sitter_rust::LANGUAGE.into()
9    }
10
11    fn language_name(&self) -> &str {
12        "rust"
13    }
14
15    fn file_extensions(&self) -> &[&str] {
16        &["rs"]
17    }
18
19    fn is_splittable(&self, node_type: &str) -> bool {
20        matches!(
21            node_type,
22            "function_item"
23                | "impl_item"
24                | "struct_item"
25                | "enum_item"
26                | "trait_item"
27                | "mod_item"
28                | "macro_definition"
29        )
30    }
31
32    fn has_nested_chunks(&self, node_type: &str) -> bool {
33        matches!(node_type, "impl_item" | "trait_item" | "mod_item")
34    }
35
36    fn classify_node(&self, node_type: &str, parent_name: Option<&str>) -> ChunkType {
37        match node_type {
38            "function_item" if parent_name.is_some() => ChunkType::Method,
39            "function_item" => ChunkType::Function,
40            "impl_item" => ChunkType::Impl,
41            "struct_item" => ChunkType::Struct,
42            "enum_item" => ChunkType::Enum,
43            "trait_item" => ChunkType::Trait,
44            "mod_item" => ChunkType::Module,
45            "macro_definition" => ChunkType::Macro,
46            _ => ChunkType::ModuleLevel,
47        }
48    }
49
50    fn extract_metadata(&self, node: tree_sitter::Node, source: &str) -> NodeMetadata {
51        let mut meta = NodeMetadata::default();
52
53        match node.kind() {
54            "function_item" => {
55                meta.name = find_name(node, source);
56                let text = &source[node.start_byte()..node.end_byte()];
57                meta.is_async = text.starts_with("async ") || text.starts_with("pub async ");
58                meta.docstring = extract_preceding_comments(node, source);
59            }
60            "impl_item" => {
61                // impl Type or impl Trait for Type
62                meta.name = find_child_text(node, source, "type_identifier");
63                meta.docstring = extract_preceding_comments(node, source);
64            }
65            "struct_item" | "enum_item" => {
66                meta.name = find_child_text(node, source, "type_identifier");
67                meta.docstring = extract_preceding_comments(node, source);
68            }
69            "trait_item" => {
70                meta.name = find_child_text(node, source, "type_identifier");
71                meta.docstring = extract_preceding_comments(node, source);
72            }
73            "mod_item" => {
74                meta.name = find_name(node, source);
75                meta.docstring = extract_preceding_comments(node, source);
76            }
77            "macro_definition" => {
78                meta.name = find_name(node, source);
79                meta.docstring = extract_preceding_comments(node, source);
80            }
81            _ => {
82                meta.name = find_name(node, source);
83                meta.docstring = extract_preceding_comments(node, source);
84            }
85        }
86
87        // Extract attributes as decorators
88        if let Some(prev) = node.prev_sibling() {
89            if prev.kind() == "attribute_item" || prev.kind() == "inner_attribute_item" {
90                let text = &source[prev.start_byte()..prev.end_byte()];
91                meta.decorators.push(text.to_string());
92            }
93        }
94
95        meta
96    }
97}