mirage-analyzer 1.3.0

Path-Aware Code Intelligence Engine for Rust
Documentation
// Mirage: Path-Aware Code Intelligence Engine
//
// A control-flow and logic graph engine for multi-language codebases.
// Extracts CFGs from Magellan (Rust via MIR, C/C++ via AST), enumerates execution paths,
// and provides graph-based reasoning capabilities.

#![allow(dead_code)]

use anyhow::Result;
use clap::Parser;

mod analysis;
mod cfg;
mod cli;
mod integrations;
mod mir;
mod output;
mod platform;
mod router;
mod storage;

use cli::{Cli, Commands};

fn main() -> Result<()> {
    // Check platform and warn about limitations
    platform::check_platform_support();

    let cli = Cli::parse();

    // Initialize tracing
    tracing_subscriber::fmt()
        .with_env_filter(
            tracing_subscriber::EnvFilter::from_default_env()
                .add_directive(tracing::Level::WARN.into()),
        )
        .init();

    // Run the appropriate command
    run_command(cli)?;

    Ok(())
}

fn run_command(cli: Cli) -> Result<()> {
    // Handle --detect-backend flag before command dispatch
    if cli.detect_backend {
        let db_str = cli
            .db
            .ok_or_else(|| anyhow::anyhow!("--db required for --detect-backend"))?;
        let db_path = std::path::Path::new(&db_str);

        use crate::storage::BackendFormat;
        let format = BackendFormat::detect(db_path)
            .map_err(|e| anyhow::anyhow!("Backend detection failed: {}", e))?;

        let backend_str = match format {
            BackendFormat::SQLite => "sqlite",
            BackendFormat::Geometric => "geometric",
            BackendFormat::Unknown => "unknown",
        };

        if matches!(
            cli.output,
            cli::OutputFormat::Json | cli::OutputFormat::Pretty
        ) {
            let output = serde_json::json!({
                "backend": backend_str,
                "database": db_str,
            });
            println!("{}", serde_json::to_string(&output)?);
        } else {
            println!("{}", backend_str);
        }
        return Ok(());
    }

    match cli.command {
        None => Err(anyhow::anyhow!(
            "No subcommand provided. Use --help for usage information."
        )),
        Some(ref cmd) => match cmd {
            Commands::Status(args) => cli::cmds::status(args, &cli),
            Commands::Paths(ref args) => cli::cmds::paths(args, &cli),
            Commands::Cfg(ref args) => cli::cmds::cfg(args, &cli),
            Commands::Dominators(ref args) => cli::cmds::dominators(args, &cli),
            Commands::Loops(ref args) => cli::cmds::loops(args, &cli),
            Commands::Unreachable(ref args) => cli::cmds::unreachable(args, &cli),
            Commands::Patterns(ref args) => cli::cmds::patterns(args, &cli),
            Commands::Frontiers(ref args) => cli::cmds::frontiers(args, &cli),
            Commands::Verify(ref args) => cli::cmds::verify(args, &cli),
            Commands::BlastZone(ref args) => cli::cmds::blast_zone(args, &cli),
            Commands::Cycles(ref args) => cli::cmds::cycles(args, &cli),
            Commands::Slice(ref args) => cli::cmds::slice(args, &cli),
            Commands::Hotspots(ref args) => cli::cmds::hotspots(args, &cli),
            Commands::Hotpaths(ref args) => cli::cmds::hotpaths(args, &cli),
            Commands::Diff(ref args) => cli::cmds::diff(args, &cli),
            Commands::Icfg(ref args) => cli::cmds::icfg(args, &cli),
            Commands::Coverage(ref args) => cli::cmds::coverage(args, &cli),
            // Commands::ComplexBlocks(ref args) => cli::cmds::complex_blocks(args, &cli),
            // Commands::SpatialAnalysis(ref args) => cli::cmds::spatial_analysis(args, &cli),
            Commands::Migrate(ref args) => cli::cmds::migrate(args, &cli),
        },
    }
}