Skip to main content

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}