1use serde::{Deserialize, Serialize};
4
5#[derive(Debug, Clone, Serialize, Deserialize)]
7pub struct Parameter {
8 pub name: String,
10 pub type_annotation: Option<String>,
12 pub default_value: Option<String>,
14}
15
16#[derive(Debug, Clone, Serialize, Deserialize)]
18pub struct Symbol {
19 pub name: String,
21 pub qualified_name: String,
23 pub kind: SymbolKind,
25 pub signature: String,
27 pub visibility: Visibility,
29 pub file_path: String,
31 pub line_start: usize,
33 pub line_end: usize,
35 pub doc_comment: Option<String>,
37 pub parent: Option<String>,
39 #[serde(default)]
41 pub parameters: Vec<Parameter>,
42 #[serde(default)]
44 pub return_type: Option<String>,
45 #[serde(default)]
47 pub is_async: bool,
48 #[serde(default)]
50 pub attributes: Vec<String>,
51 #[serde(default)]
53 pub throws: Vec<String>,
54 #[serde(default)]
56 pub generic_params: Option<String>,
57 #[serde(default)]
59 pub is_abstract: bool,
60}
61
62#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
64pub enum SymbolKind {
65 Function,
66 Method,
67 Class,
68 Struct,
69 Enum,
70 Interface, Type, Constant,
73 Module,
74 Test,
75 Field, Property, Constructor, EnumVariant, Macro, Decorator, }
82
83impl std::fmt::Display for SymbolKind {
84 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
85 match self {
86 Self::Function => write!(f, "function"),
87 Self::Method => write!(f, "method"),
88 Self::Class => write!(f, "class"),
89 Self::Struct => write!(f, "struct"),
90 Self::Enum => write!(f, "enum"),
91 Self::Interface => write!(f, "interface"),
92 Self::Type => write!(f, "type"),
93 Self::Constant => write!(f, "constant"),
94 Self::Module => write!(f, "module"),
95 Self::Test => write!(f, "test"),
96 Self::Field => write!(f, "field"),
97 Self::Property => write!(f, "property"),
98 Self::Constructor => write!(f, "constructor"),
99 Self::EnumVariant => write!(f, "enum_variant"),
100 Self::Macro => write!(f, "macro"),
101 Self::Decorator => write!(f, "decorator"),
102 }
103 }
104}
105
106#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
108pub enum Visibility {
109 Public,
110 Private,
111 Crate, Protected, }
114
115impl std::fmt::Display for Visibility {
116 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
117 match self {
118 Self::Public => write!(f, "public"),
119 Self::Private => write!(f, "private"),
120 Self::Crate => write!(f, "crate"),
121 Self::Protected => write!(f, "protected"),
122 }
123 }
124}
125
126#[derive(Debug, Clone, Serialize, Deserialize)]
128pub struct Reference {
129 pub source_qualified_name: String,
131 pub target_name: String,
133 pub kind: ReferenceKind,
135 pub file_path: String,
137 pub line: usize,
139}
140
141#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
143pub enum ReferenceKind {
144 Call,
145 Import,
146 Inherits,
147 Implements,
148 TypeUsage,
149}
150
151impl std::str::FromStr for SymbolKind {
152 type Err = String;
153
154 fn from_str(s: &str) -> Result<Self, Self::Err> {
155 match s {
156 "function" => Ok(SymbolKind::Function),
157 "method" => Ok(SymbolKind::Method),
158 "class" => Ok(SymbolKind::Class),
159 "struct" => Ok(SymbolKind::Struct),
160 "enum" => Ok(SymbolKind::Enum),
161 "interface" => Ok(SymbolKind::Interface),
162 "type" => Ok(SymbolKind::Type),
163 "constant" => Ok(SymbolKind::Constant),
164 "module" => Ok(SymbolKind::Module),
165 "test" => Ok(SymbolKind::Test),
166 "field" => Ok(SymbolKind::Field),
167 "property" => Ok(SymbolKind::Property),
168 "constructor" => Ok(SymbolKind::Constructor),
169 "enum_variant" => Ok(SymbolKind::EnumVariant),
170 "macro" => Ok(SymbolKind::Macro),
171 "decorator" => Ok(SymbolKind::Decorator),
172 _ => Err(format!("Unknown SymbolKind: {s}")),
173 }
174 }
175}
176
177pub fn symbol_kind_from_str(s: &str) -> Option<SymbolKind> {
179 s.parse().ok()
180}
181
182pub fn visibility_from_str(s: &str) -> Visibility {
184 match s {
185 "public" => Visibility::Public,
186 "crate" => Visibility::Crate,
187 "protected" => Visibility::Protected,
188 _ => Visibility::Private,
189 }
190}
191
192fn symbol_kind_from_node_kind(nk: &codemem_core::NodeKind) -> SymbolKind {
198 match nk {
199 codemem_core::NodeKind::Function => SymbolKind::Function,
200 codemem_core::NodeKind::Method => SymbolKind::Method,
201 codemem_core::NodeKind::Class => SymbolKind::Class,
202 codemem_core::NodeKind::Interface => SymbolKind::Interface,
203 codemem_core::NodeKind::Type => SymbolKind::Type,
204 codemem_core::NodeKind::Constant => SymbolKind::Constant,
205 codemem_core::NodeKind::Module => SymbolKind::Module,
206 codemem_core::NodeKind::Test => SymbolKind::Test,
207 _ => SymbolKind::Function, }
209}
210
211pub fn symbol_from_graph_node(node: &codemem_core::GraphNode) -> Option<Symbol> {
216 let qualified_name = node.id.strip_prefix("sym:")?.to_string();
217
218 let kind = node
220 .payload
221 .get("symbol_kind")
222 .and_then(|v| v.as_str())
223 .and_then(symbol_kind_from_str)
224 .unwrap_or_else(|| symbol_kind_from_node_kind(&node.kind));
225
226 let file_path = node
227 .payload
228 .get("file_path")
229 .and_then(|v| v.as_str())
230 .unwrap_or("")
231 .to_string();
232
233 let signature = node
234 .payload
235 .get("signature")
236 .and_then(|v| v.as_str())
237 .unwrap_or("")
238 .to_string();
239
240 let visibility = node
241 .payload
242 .get("visibility")
243 .and_then(|v| v.as_str())
244 .map(visibility_from_str)
245 .unwrap_or(Visibility::Private);
246
247 let line_start = node
248 .payload
249 .get("line_start")
250 .and_then(|v| v.as_u64())
251 .unwrap_or(0) as usize;
252
253 let line_end = node
254 .payload
255 .get("line_end")
256 .and_then(|v| v.as_u64())
257 .unwrap_or(0) as usize;
258
259 let doc_comment = node
260 .payload
261 .get("doc_comment")
262 .and_then(|v| v.as_str())
263 .map(|s| s.to_string());
264
265 let name = qualified_name
267 .rsplit("::")
268 .next()
269 .unwrap_or(&qualified_name)
270 .to_string();
271
272 let parameters: Vec<Parameter> = node
273 .payload
274 .get("parameters")
275 .and_then(|v| serde_json::from_value(v.clone()).ok())
276 .unwrap_or_default();
277
278 let return_type = node
279 .payload
280 .get("return_type")
281 .and_then(|v| v.as_str())
282 .map(|s| s.to_string());
283
284 let is_async = node
285 .payload
286 .get("is_async")
287 .and_then(|v| v.as_bool())
288 .unwrap_or(false);
289
290 let attributes: Vec<String> = node
291 .payload
292 .get("attributes")
293 .and_then(|v| serde_json::from_value(v.clone()).ok())
294 .unwrap_or_default();
295
296 let throws: Vec<String> = node
297 .payload
298 .get("throws")
299 .and_then(|v| serde_json::from_value(v.clone()).ok())
300 .unwrap_or_default();
301
302 let generic_params = node
303 .payload
304 .get("generic_params")
305 .and_then(|v| v.as_str())
306 .map(|s| s.to_string());
307
308 let is_abstract = node
309 .payload
310 .get("is_abstract")
311 .and_then(|v| v.as_bool())
312 .unwrap_or(false);
313
314 let parent = node
315 .payload
316 .get("parent")
317 .and_then(|v| v.as_str())
318 .map(|s| s.to_string());
319
320 Some(Symbol {
321 name,
322 qualified_name,
323 kind,
324 signature,
325 visibility,
326 file_path,
327 line_start,
328 line_end,
329 doc_comment,
330 parent,
331 parameters,
332 return_type,
333 is_async,
334 attributes,
335 throws,
336 generic_params,
337 is_abstract,
338 })
339}
340
341impl From<SymbolKind> for codemem_core::NodeKind {
342 fn from(kind: SymbolKind) -> Self {
343 match kind {
344 SymbolKind::Function => codemem_core::NodeKind::Function,
345 SymbolKind::Method => codemem_core::NodeKind::Method,
346 SymbolKind::Class => codemem_core::NodeKind::Class,
347 SymbolKind::Struct => codemem_core::NodeKind::Class,
348 SymbolKind::Enum => codemem_core::NodeKind::Class,
349 SymbolKind::Interface => codemem_core::NodeKind::Interface,
350 SymbolKind::Type => codemem_core::NodeKind::Type,
351 SymbolKind::Constant => codemem_core::NodeKind::Constant,
352 SymbolKind::Module => codemem_core::NodeKind::Module,
353 SymbolKind::Test => codemem_core::NodeKind::Test,
354 SymbolKind::Field => codemem_core::NodeKind::Constant,
355 SymbolKind::Property => codemem_core::NodeKind::Constant,
356 SymbolKind::Constructor => codemem_core::NodeKind::Method,
357 SymbolKind::EnumVariant => codemem_core::NodeKind::Constant,
358 SymbolKind::Macro => codemem_core::NodeKind::Function,
359 SymbolKind::Decorator => codemem_core::NodeKind::Function,
360 }
361 }
362}
363
364impl std::fmt::Display for ReferenceKind {
365 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
366 match self {
367 Self::Call => write!(f, "call"),
368 Self::Import => write!(f, "import"),
369 Self::Inherits => write!(f, "inherits"),
370 Self::Implements => write!(f, "implements"),
371 Self::TypeUsage => write!(f, "type_usage"),
372 }
373 }
374}