splice/graph/magellan_integration/types.rs
1//! Shared types for Magellan integration.
2
3use magellan::SymbolQueryResult;
4
5/// Backend type identifier.
6#[derive(Debug, Clone, Copy, PartialEq, Eq)]
7/// Backend type for Magellan integration.
8pub enum IntegrationBackend {
9 /// SQLite database backend.
10 Sqlite,
11 /// Geometric spatial backend.
12 #[cfg(feature = "geometric")]
13 Geometric,
14}
15
16/// Symbol information extracted from Magellan's SymbolQueryResult.
17#[derive(Debug, Clone)]
18pub struct SymbolInfo {
19 /// Entity ID in the graph database.
20 pub entity_id: i64,
21 /// Symbol name.
22 pub name: String,
23 /// File path containing the symbol.
24 pub file_path: String,
25 /// Symbol kind (e.g., "fn", "struct", "class").
26 pub kind: String,
27 /// Byte offset where the symbol starts.
28 pub byte_start: usize,
29 /// Byte offset where the symbol ends.
30 pub byte_end: usize,
31 /// Line number where the symbol starts (1-indexed).
32 pub start_line: Option<usize>,
33 /// Line number where the symbol ends (1-indexed).
34 pub end_line: Option<usize>,
35}
36
37/// Symbol with optional call relationship context.
38#[derive(Debug, Clone)]
39pub struct SymbolWithRelations {
40 /// The symbol's basic information.
41 pub symbol: SymbolInfo,
42 /// Symbols that call this symbol (if --with-callers flag).
43 pub callers: Vec<SymbolInfo>,
44 /// Symbols that this symbol calls (if --with-callees flag).
45 pub callees: Vec<SymbolInfo>,
46}
47
48/// Direction for call relationship traversal.
49#[derive(Debug, Clone, Copy, PartialEq, Eq)]
50pub enum CallDirection {
51 /// Get callers only (symbols that call this symbol).
52 In,
53 /// Get callees only (symbols that this symbol calls).
54 Out,
55 /// Get both callers and callees.
56 Both,
57}
58
59/// Location of a call in source code.
60#[derive(Debug, Clone)]
61pub struct CallSite {
62 /// File path containing the call.
63 pub file_path: String,
64 /// Byte offset where call starts.
65 pub byte_start: usize,
66 /// Byte offset where call ends.
67 pub byte_end: usize,
68 /// Line number where call starts (1-indexed).
69 pub start_line: usize,
70 /// Column number where call starts (0-indexed).
71 pub start_col: usize,
72 /// Line number where call ends (1-indexed).
73 pub end_line: usize,
74 /// Column number where call ends (0-indexed).
75 pub end_col: usize,
76}
77
78/// A call relationship reference with symbol and call site.
79#[derive(Debug, Clone)]
80pub struct CallReference {
81 /// The symbol being referenced (caller or callee).
82 pub symbol: SymbolInfo,
83 /// Location of the call site.
84 pub call_site: CallSite,
85}
86
87/// Call relationships for a symbol.
88#[derive(Debug, Clone)]
89pub struct CallRelationships {
90 /// The symbol whose relationships are being queried.
91 pub symbol: SymbolInfo,
92 /// Symbols that call this symbol (if direction is In or Both).
93 pub callers: Vec<CallReference>,
94 /// Symbols that this symbol calls (if direction is Out or Both).
95 pub callees: Vec<CallReference>,
96}
97
98/// A symbol in reachability analysis with depth and path.
99#[derive(Debug, Clone)]
100pub struct ReachableSymbol {
101 /// The symbol's basic information.
102 pub symbol: SymbolInfo,
103 /// Depth from root (0 = root, 1 = direct relationship, etc.).
104 pub depth: usize,
105 /// Call path from root to this symbol.
106 pub path: Vec<String>,
107}
108
109/// A dead (unreachable) symbol.
110#[derive(Debug, Clone)]
111pub struct DeadSymbol {
112 /// The symbol's basic information.
113 pub symbol: SymbolInfo,
114 /// Reason why this symbol is considered dead.
115 pub reason: String,
116}
117
118/// Information about a detected cycle.
119#[derive(Debug, Clone)]
120pub struct CycleInfo {
121 /// Unique cycle identifier.
122 pub id: String,
123 /// Number of symbols in the cycle.
124 pub size: usize,
125 /// Symbols in the cycle.
126 pub members: Vec<SymbolInfo>,
127 /// Representative symbol (e.g., alphabetically first).
128 pub representative: SymbolInfo,
129 /// Whether this is a self-loop (single symbol calling itself).
130 pub is_self_loop: bool,
131}
132
133/// Condensation graph result (SCCs collapsed to DAG).
134#[derive(Debug, Clone)]
135pub struct CondensationGraph {
136 /// Total number of SCCs.
137 pub scc_count: usize,
138 /// Number of SCCs that are cycles.
139 pub cycle_scc_count: usize,
140 /// Number of singleton SCCs.
141 pub singleton_count: usize,
142 /// SCCs in the graph.
143 pub sccs: Vec<CondensedScc>,
144 /// Edges between SCCs.
145 pub edges: Vec<SccEdge>,
146 /// Topological levels.
147 pub levels: Vec<LevelInfo>,
148}
149
150/// A condensed SCC.
151#[derive(Debug, Clone)]
152/// A condensed strongly connected component.
153pub struct CondensedScc {
154 /// Unique identifier for the SCC.
155 pub id: String,
156 /// Number of symbols in the SCC.
157 pub size: usize,
158 /// Whether the SCC contains a cycle.
159 pub is_cycle: bool,
160 /// Member symbols, if expanded.
161 pub members: Option<Vec<SymbolInfo>>,
162 /// Representative symbol for the SCC.
163 pub representative: SymbolInfo,
164}
165
166/// Edge between SCCs.
167#[derive(Debug, Clone)]
168/// Edge between two strongly connected components.
169pub struct SccEdge {
170 /// Source SCC identifier.
171 pub from: String,
172 /// Target SCC identifier.
173 pub to: String,
174 /// Number of edges between the SCCs.
175 pub weight: usize,
176}
177
178/// Topological level.
179#[derive(Debug, Clone)]
180/// Topological level in the condensation graph.
181pub struct LevelInfo {
182 /// Level number in topological order.
183 pub level: usize,
184 /// SCC identifiers at this level.
185 pub scc_ids: Vec<String>,
186 /// Number of SCCs at this level.
187 pub count: usize,
188}
189
190/// Configuration for DOT graph generation.
191#[derive(Debug, Clone)]
192pub struct ImpactDotConfig {
193 /// Show symbol kinds in node labels (e.g., "main (fn)").
194 pub show_symbol_kinds: bool,
195 /// Maximum depth for traversal (None = unlimited).
196 pub max_depth: Option<usize>,
197 /// Symbol to highlight in graph (fillcolor=lightblue).
198 pub highlight_symbol: Option<String>,
199}
200
201impl Default for ImpactDotConfig {
202 fn default() -> Self {
203 Self {
204 show_symbol_kinds: true,
205 max_depth: Some(10),
206 highlight_symbol: None,
207 }
208 }
209}
210
211/// A symbol in a program slice.
212#[derive(Debug, Clone)]
213pub struct SlicedSymbol {
214 /// The symbol.
215 pub symbol: SymbolInfo,
216 /// Distance from target.
217 pub distance: usize,
218 /// Whether this is the target symbol.
219 pub is_target: bool,
220 /// Relationship type.
221 pub relationship: String,
222}
223
224/// File metadata with optional symbol count.
225#[derive(Debug, Clone)]
226pub struct FileMetadata {
227 /// Path to the file.
228 pub path: String,
229 /// Content hash of the file.
230 pub hash: String,
231 /// Unix timestamp when file was last indexed.
232 pub last_indexed_at: i64,
233 /// Unix timestamp when file was last modified.
234 pub last_modified: i64,
235 /// Symbol count if requested (None if --symbols flag not provided).
236 pub symbol_count: Option<usize>,
237}
238
239impl From<SymbolQueryResult> for SymbolInfo {
240 fn from(result: SymbolQueryResult) -> Self {
241 Self {
242 entity_id: result.entity_id,
243 name: result.name,
244 file_path: result.file_path,
245 kind: result.kind,
246 byte_start: result.byte_start,
247 byte_end: result.byte_end,
248 start_line: None,
249 end_line: None,
250 }
251 }
252}
253
254/// Code chunk with content and metadata.
255#[derive(Debug, Clone)]
256pub struct CodeChunk {
257 /// Source code content.
258 pub content: String,
259 /// File path containing this chunk.
260 pub file_path: String,
261 /// Byte offset where the chunk starts.
262 pub byte_start: usize,
263 /// Byte offset where the chunk ends.
264 pub byte_end: usize,
265 /// Symbol name if this chunk belongs to a specific symbol.
266 pub symbol_name: Option<String>,
267 /// Symbol kind if available.
268 pub symbol_kind: Option<String>,
269}
270
271impl CodeChunk {
272 /// Return the length of the chunk content in bytes.
273 pub fn len(&self) -> usize {
274 self.content.len()
275 }
276
277 /// Check if the chunk content is empty.
278 pub fn is_empty(&self) -> bool {
279 self.content.is_empty()
280 }
281
282 /// Return the chunk content as bytes.
283 pub fn as_bytes(&self) -> &[u8] {
284 self.content.as_bytes()
285 }
286
287 /// Iterate over lines in the chunk content.
288 pub fn lines(&self) -> std::str::Lines<'_> {
289 self.content.lines()
290 }
291}
292
293impl From<magellan::CodeChunk> for CodeChunk {
294 fn from(chunk: magellan::CodeChunk) -> Self {
295 Self {
296 content: chunk.content,
297 file_path: chunk.file_path,
298 byte_start: chunk.byte_start,
299 byte_end: chunk.byte_end,
300 symbol_name: chunk.symbol_name,
301 symbol_kind: chunk.symbol_kind,
302 }
303 }
304}
305
306/// Database statistics for Magellan graph.
307#[derive(Debug, Clone)]
308pub struct DatabaseStats {
309 /// Number of indexed files.
310 pub files: usize,
311 /// Number of indexed symbols.
312 pub symbols: usize,
313 /// Number of indexed references.
314 pub references: usize,
315 /// Number of indexed function calls.
316 pub calls: usize,
317 /// Number of stored code chunks.
318 pub code_chunks: usize,
319}