pub struct MagellanBridge { /* private fields */ }Expand description
Bridge to Magellan’s inter-procedural graph algorithms
Wraps CodeGraph to provide access to call graph algorithms including:
- Reachability analysis (forward/reverse)
- Dead code detection
- Cycle detection (mutual recursion)
- Program slicing
- Path enumeration
§Example
use mirage_analyzer::analysis::MagellanBridge;
// Open existing Magellan database
let bridge = MagellanBridge::open("codemcp/mirage.db")?;
// Find all functions reachable from main
let reachable = bridge.reachable_symbols("main")?;
println!("Found {} reachable functions", reachable.len());
// Find dead code unreachable from entry points
let dead = bridge.graph().dead_symbols("main")?;
println!("Found {} dead symbols", dead.len());Implementations§
Source§impl MagellanBridge
impl MagellanBridge
Sourcepub fn open(db_path: &str) -> Result<Self>
pub fn open(db_path: &str) -> Result<Self>
Open a Magellan database for inter-procedural analysis
§Arguments
db_path- Path to the Magellan database file (typicallycodemcp/mirage.db)
§Returns
A MagellanBridge instance ready for analysis
§Example
use mirage_analyzer::analysis::MagellanBridge;
let bridge = MagellanBridge::open("codemcp/mirage.db")?;Sourcepub fn graph(&self) -> &CodeGraph
pub fn graph(&self) -> &CodeGraph
Get a reference to the underlying Magellan CodeGraph
Provides direct access to all Magellan algorithms for advanced use cases.
§Example
use mirage_analyzer::analysis::MagellanBridge;
let bridge = MagellanBridge::open("codemcp/mirage.db")?;
// Access full CodeGraph API
let cycles = bridge.graph().detect_cycles()?;Sourcepub fn reachable_symbols(&self, symbol_id: &str) -> Result<Vec<SymbolInfo>>
pub fn reachable_symbols(&self, symbol_id: &str) -> Result<Vec<SymbolInfo>>
Find all symbols reachable from a given symbol (forward reachability)
Computes the transitive closure of the call graph starting from the specified symbol. This is useful for:
- Impact analysis (what does changing this symbol affect?)
- Test coverage (what code does this test exercise?)
- Dependency tracing
§Arguments
symbol_id- Stable symbol ID (32-char BLAKE3 hash) or FQN
§Returns
Vector of SymbolInfo for reachable symbols, sorted deterministically
§Example
use mirage_analyzer::analysis::MagellanBridge;
let bridge = MagellanBridge::open("codemcp/mirage.db")?;
// Find all functions called from main (directly or indirectly)
let reachable = bridge.reachable_symbols("main")?;
for symbol in reachable {
println!(" - {}", symbol.fqn.as_deref().unwrap_or("?"));
}Sourcepub fn reverse_reachable_symbols(
&self,
symbol_id: &str,
) -> Result<Vec<SymbolInfo>>
pub fn reverse_reachable_symbols( &self, symbol_id: &str, ) -> Result<Vec<SymbolInfo>>
Find all symbols that can reach a given symbol (reverse reachability)
Computes the reverse transitive closure of the call graph. Returns all symbols from which the specified symbol can be reached (i.e., all callers). This is useful for:
- Bug isolation (what code affects this symbol?)
- Refactoring safety (what needs to be updated?)
- Root cause analysis
§Arguments
symbol_id- Stable symbol ID (32-char BLAKE3 hash) or FQN
§Returns
Vector of SymbolInfo for symbols that can reach the target
§Example
use mirage_analyzer::analysis::MagellanBridge;
let bridge = MagellanBridge::open("codemcp/mirage.db")?;
// Find all functions that call 'helper_function'
let callers = bridge.reverse_reachable_symbols("helper_function")?;
println!("{} functions call this", callers.len());Sourcepub fn dead_symbols(&self, entry_symbol_id: &str) -> Result<Vec<DeadSymbol>>
pub fn dead_symbols(&self, entry_symbol_id: &str) -> Result<Vec<DeadSymbol>>
Find dead code unreachable from an entry point symbol
Identifies all symbols in the call graph that cannot be reached from
the specified entry point (e.g., main, test_main).
§Limitations
- Only considers the call graph
- Symbols called via reflection, function pointers, or dynamic dispatch may be incorrectly flagged
- Test functions and platform-specific code may appear as dead code
§Arguments
entry_symbol_id- Stable symbol ID of the entry point (e.g., main function)
§Returns
Vector of DeadSymbol for unreachable symbols
§Example
use mirage_analyzer::analysis::MagellanBridge;
use mirage_analyzer::cli::DeadSymbolJson;
let bridge = MagellanBridge::open("codemcp/mirage.db")?;
// Find all functions unreachable from main
let dead = bridge.dead_symbols("main")?;
for dead_symbol in &dead {
println!("Dead: {} ({})",
dead_symbol.symbol.fqn.as_deref().unwrap_or("?"),
dead_symbol.reason);
}
// Convert to JSON-serializable format
let json_symbols: Vec<DeadSymbolJson> = dead.iter().map(|d| d.into()).collect();Sourcepub fn detect_cycles(&self) -> Result<CycleReport>
pub fn detect_cycles(&self) -> Result<CycleReport>
Detect cycles in the call graph using SCC decomposition
Finds all strongly connected components (SCCs) with more than one member, which indicate cycles or mutual recursion in the call graph.
§Returns
CycleReport containing all detected cycles
§Example
use mirage_analyzer::analysis::MagellanBridge;
let bridge = MagellanBridge::open("codemcp/mirage.db")?;
let report = bridge.detect_cycles()?;
println!("Found {} cycles", report.total_count);
for cycle in &report.cycles {
println!("Cycle with {} members:", cycle.members.len());
for member in &cycle.members {
println!(" - {}", member.fqn.as_deref().unwrap_or("?"));
}
}Sourcepub fn backward_slice(&self, symbol_id: &str) -> Result<SliceWrapper>
pub fn backward_slice(&self, symbol_id: &str) -> Result<SliceWrapper>
Compute a backward program slice (what affects this symbol)
Returns all symbols that can affect the target symbol through the call graph. This is useful for bug isolation.
§Note
Current implementation uses call-graph reachability as a fallback. Full CFG-based program slicing will be available in future versions.
§Arguments
symbol_id- Stable symbol ID or FQN to slice from
§Returns
SliceResult containing the slice and statistics
§Example
use mirage_analyzer::analysis::MagellanBridge;
let bridge = MagellanBridge::open("codemcp/mirage.db")?;
// Find what affects 'helper_function'
let slice_result = bridge.backward_slice("helper_function")?;
println!("{} symbols affect this function", slice_result.symbol_count);Sourcepub fn forward_slice(&self, symbol_id: &str) -> Result<SliceWrapper>
pub fn forward_slice(&self, symbol_id: &str) -> Result<SliceWrapper>
Compute a forward program slice (what this symbol affects)
Returns all symbols that the target symbol can affect through the call graph. This is useful for refactoring safety.
§Note
Current implementation uses call-graph reachability as a fallback. Full CFG-based program slicing will be available in future versions.
§Arguments
symbol_id- Stable symbol ID or FQN to slice from
§Returns
SliceWrapper containing the slice and statistics
§Example
use mirage_analyzer::analysis::MagellanBridge;
let bridge = MagellanBridge::open("codemcp/mirage.db")?;
// Find what 'main_function' affects
let slice_result = bridge.forward_slice("main_function")?;
println!("{} symbols are affected by this function", slice_result.symbol_count);Sourcepub fn enumerate_paths(
&self,
start_symbol_id: &str,
end_symbol_id: Option<&str>,
max_depth: usize,
max_paths: usize,
) -> Result<PathEnumerationResult>
pub fn enumerate_paths( &self, start_symbol_id: &str, end_symbol_id: Option<&str>, max_depth: usize, max_paths: usize, ) -> Result<PathEnumerationResult>
Enumerate execution paths from a starting symbol
Finds all execution paths from start_symbol_id to end_symbol_id (if provided)
or all paths starting from start_symbol_id (if end_symbol_id is None).
Path enumeration uses bounded DFS to prevent infinite traversal in cyclic graphs.
§Arguments
start_symbol_id- Starting symbol ID or FQNend_symbol_id- Optional ending symbol ID or FQNmax_depth- Maximum path depth (default: 100)max_paths- Maximum number of paths to return (default: 1000)
§Returns
PathEnumerationResult with all discovered paths and statistics
§Example
use mirage_analyzer::analysis::MagellanBridge;
let bridge = MagellanBridge::open("codemcp/mirage.db")?;
// Find all paths from main to any leaf function
let result = bridge.enumerate_paths("main", None, 50, 100)?;
println!("Found {} paths", result.total_enumerated);
println!("Average length: {:.2}", result.statistics.avg_length);Sourcepub fn enumerate_paths_json(
&self,
start_symbol_id: &str,
end_symbol_id: Option<&str>,
max_depth: usize,
max_paths: usize,
) -> Result<PathEnumerationJson>
pub fn enumerate_paths_json( &self, start_symbol_id: &str, end_symbol_id: Option<&str>, max_depth: usize, max_paths: usize, ) -> Result<PathEnumerationJson>
Enumerate paths and return JSON-serializable result
Convenience method that wraps PathEnumerationResult in a
JSON-serializable format for CLI output.
§Arguments
start_symbol_id- Starting symbol ID or FQNend_symbol_id- Optional ending symbol ID or FQNmax_depth- Maximum path depth (default: 100)max_paths- Maximum number of paths to return (default: 1000)
§Returns
JSON-serializable path enumeration result
§Example
use mirage_analyzer::analysis::MagellanBridge;
let bridge = MagellanBridge::open("codemcp/mirage.db")?;
let result = bridge.enumerate_paths_json("main", None, 50, 100)?;
println!("Found {} paths", result.total_enumerated);Sourcepub fn condense_call_graph(&self) -> Result<CondensationResult>
pub fn condense_call_graph(&self) -> Result<CondensationResult>
Condense the call graph by collapsing SCCs into supernodes
Creates a condensation DAG by collapsing each strongly connected component into a single “supernode”. The resulting graph is always acyclic.
§Use Cases
- Topological Sorting: Condensation graph is a DAG
- Mutual Recursion Detection: Large supernodes indicate tight coupling
- Impact Analysis: Changing one symbol affects its entire SCC
- Inter-procedural Dominance: Functions in root supernodes dominate downstream functions
§Returns
CondensationResult with the condensed DAG and symbol-to-supernode mapping
§Example
use mirage_analyzer::analysis::MagellanBridge;
let bridge = MagellanBridge::open("codemcp/mirage.db")?;
let condensed = bridge.condense_call_graph()?;
println!("Condensed to {} supernodes", condensed.graph.supernodes.len());
println!("Condensed graph has {} edges", condensed.graph.edges.len());Sourcepub fn condense_call_graph_json(&self) -> Result<CondensationJson>
pub fn condense_call_graph_json(&self) -> Result<CondensationJson>
Condense call graph and return JSON-serializable result
Convenience method that wraps CondensationResult in a
JSON-serializable format for CLI output.
§Returns
CondensationJson with condensed DAG summary and supernode details
§Example
use mirage_analyzer::analysis::MagellanBridge;
let bridge = MagellanBridge::open("codemcp/mirage.db")?;
let condensed = bridge.condense_call_graph_json()?;
println!("Condensed to {} supernodes", condensed.supernode_count);
println!("Largest SCC has {} functions", condensed.largest_scc_size);Auto Trait Implementations§
impl Freeze for MagellanBridge
impl !RefUnwindSafe for MagellanBridge
impl !Send for MagellanBridge
impl !Sync for MagellanBridge
impl Unpin for MagellanBridge
impl UnsafeUnpin for MagellanBridge
impl !UnwindSafe for MagellanBridge
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more