1use crate::language_registry::Language;
4use serde::Deserialize;
5use serde::Serialize;
6use tree_sitter::Tree;
7
8#[derive(Debug, Clone)]
10pub struct ParsedAst {
11 pub tree: Tree,
12 pub source: String,
13 pub language: Language,
14 pub root_node: AstNode,
15}
16
17#[derive(Debug, Clone, Serialize, Deserialize)]
19pub struct AstNode {
20 pub kind: String,
21 pub start_byte: usize,
22 pub end_byte: usize,
23 pub start_position: (usize, usize), pub end_position: (usize, usize), pub children_count: usize,
26}
27
28#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
30pub struct SourceLocation {
31 pub file_path: String,
32 pub start_line: usize,
33 pub start_column: usize,
34 pub end_line: usize,
35 pub end_column: usize,
36 pub byte_range: (usize, usize),
37}
38
39impl SourceLocation {
40 pub fn new(
42 file_path: impl Into<String>,
43 start_line: usize,
44 start_column: usize,
45 end_line: usize,
46 end_column: usize,
47 byte_range: (usize, usize),
48 ) -> Self {
49 Self {
50 file_path: file_path.into(),
51 start_line,
52 start_column,
53 end_line,
54 end_column,
55 byte_range,
56 }
57 }
58
59 pub fn as_string(&self) -> String {
61 format!(
62 "{}:{}:{}",
63 self.file_path, self.start_line, self.start_column
64 )
65 }
66
67 pub fn to_range_string(&self) -> String {
69 if self.start_line == self.end_line {
70 format!(
71 "{}:{}:{}-{}",
72 self.file_path, self.start_line, self.start_column, self.end_column
73 )
74 } else {
75 format!(
76 "{}:{}:{}-{}:{}",
77 self.file_path, self.start_line, self.start_column, self.end_line, self.end_column
78 )
79 }
80 }
81}
82
83impl std::fmt::Display for SourceLocation {
84 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
85 write!(
86 f,
87 "{}:{}:{}",
88 self.file_path, self.start_line, self.start_column
89 )
90 }
91}
92
93#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
95pub enum AstNodeKind {
96 Function,
97 Class,
98 Struct,
99 Enum,
100 Interface,
101 Trait,
102 Module,
103 Variable,
104 Constant,
105 Type,
106 Import,
107 Comment,
108 Other,
109}
110
111impl AstNodeKind {
112 pub fn from_node_type(node_type: &str) -> Self {
114 match node_type {
115 "function_declaration"
116 | "function_definition"
117 | "function_item"
118 | "method_declaration"
119 | "method_definition" => Self::Function,
120
121 "class_declaration" | "class_definition" => Self::Class,
122
123 "struct_item" | "struct_declaration" => Self::Struct,
124
125 "enum_item" | "enum_declaration" => Self::Enum,
126
127 "interface_declaration" | "protocol_declaration" => Self::Interface,
128
129 "trait_item" | "trait_declaration" => Self::Trait,
130
131 "module" | "module_declaration" | "namespace" => Self::Module,
132
133 "variable_declaration" | "let_declaration" | "const_item" => Self::Variable,
134
135 "constant_declaration" => Self::Constant,
136
137 "type_alias" | "type_definition" | "typedef" => Self::Type,
138
139 "import_statement" | "use_declaration" | "import_declaration" => Self::Import,
140
141 "comment" | "line_comment" | "block_comment" | "doc_comment" => Self::Comment,
142
143 _ => Self::Other,
144 }
145 }
146}
147
148#[derive(Debug, Clone, Serialize, Deserialize)]
150pub struct CodeChunk {
151 pub id: String,
152 pub level: ChunkLevel,
153 pub kind: AstNodeKind,
154 pub name: String,
155 pub content: String,
156 pub location: SourceLocation,
157 pub parent_id: Option<String>,
158 pub children_ids: Vec<String>,
159 pub metadata: ChunkMetadata,
160}
161
162#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
164pub enum ChunkLevel {
165 File,
166 Module,
167 Class,
168 Function,
169 Block,
170}
171
172impl ChunkLevel {
173 pub const fn name(&self) -> &'static str {
175 match self {
176 Self::File => "File",
177 Self::Module => "Module",
178 Self::Class => "Class",
179 Self::Function => "Function",
180 Self::Block => "Block",
181 }
182 }
183}
184
185#[derive(Debug, Clone, Serialize, Deserialize)]
187pub struct ChunkMetadata {
188 pub language: Language,
189 pub complexity: usize,
190 pub token_count: usize,
191 pub line_count: usize,
192 pub has_tests: bool,
193 pub has_docs: bool,
194 pub visibility: Visibility,
195 pub dependencies: Vec<String>,
196 pub symbols_defined: Vec<String>,
197 pub symbols_used: Vec<String>,
198}
199
200#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
202pub enum Visibility {
203 Public,
204 Protected,
205 Private,
206 Internal,
207 Package,
208}
209
210impl Visibility {
211 pub fn from_text(text: &str) -> Self {
213 if text.contains("public") || text.contains("pub") || text.contains("export") {
214 Self::Public
215 } else if text.contains("protected") {
216 Self::Protected
217 } else if text.contains("private") || text.contains("priv") {
218 Self::Private
219 } else if text.contains("internal") {
220 Self::Internal
221 } else if text.contains("package") {
222 Self::Package
223 } else {
224 Self::Public
226 }
227 }
228}