code-buster 0.10.0

Repository-aware static analysis for AI-assisted development
Documentation
mod app;
mod engine;
mod graph;
mod languages;
mod model;
mod reporting;
mod rules;

use app::cli;
use app::commands::{
    baseline as baseline_command, completions as completions_command,
    complexity as complexity_command, config as config_command, dead as dead_command,
    doctor as doctor_command, duplication as duplication_command, explain as explain_command,
    fix as fix_command, graph as graph_command, hotspots as hotspots_command, init as init_command,
    quality as quality_command, repository_view as repository_view_command, rules as rules_command,
    structure as structure_command, summary as summary_command, update as update_command,
    workflow as workflow_command,
};
use engine::{
    analysis_cache, analysis_engine, discovery, finding_controls, preview, repository_defaults,
    semantic_diff, source_analysis_context,
};
use graph::{
    architecture as architecture_graph, dead_analysis, dependency as dependency_graph,
    export_analysis,
};
use languages::{
    cpp::rules as cpp_rules,
    csharp::rules as csharp_rules,
    css::rules as css_rules,
    dart::{
        analyzer_config as dart_analyzer_config, core as dart_core_rules,
        flutter_build as dart_flutter_build, lifecycle as dart_lifecycle,
        model_contracts as dart_model_contracts, model_duplication as dart_model_duplication,
        mvvm as dart_mvvm_rules, null_assertion as dart_null_assertion, oop as dart_oop_rules,
        package_cycle as dart_package_cycle, performance as dart_performance,
        reliability as dart_reliability, security as dart_security,
    },
    functions as function_sources,
    go::rules as go_rules,
    html::rules as html_rules,
    java::rules as java_rules,
    lua::rules as lua_rules,
    mojo::rules as mojo_rules,
    nim::rules as nim_rules,
    python::rules as python_rules,
    rust::rules as rust_rules,
    sql::rules as sql_rules,
    typescript::rules as typescript_rules,
    wren::rules as wren_rules,
};
use model::{config, findings};
use reporting::{report, sarif_ingestion};
use rules::{
    advanced_duplication, ai_security as ai_security_rules, cargo as cargo_rules,
    catalog as rule_catalog, clean_code as clean_code_rules, complexity, constant_arguments,
    diff_quality as diff_quality_rules, duplication, feature_flags,
    frameworks::{
        fastapi as fastapi_rules, flutter as flutter_quality_rules, pixijs as pixijs_rules,
        svelte as svelte_rules,
    },
    generated_code_risks, generic as generic_rules, github_actions as github_actions_rules,
    layout as layout_rules, object_soup as object_soup_rules, oop as oop_rules,
    pattern as pattern_rules, regex as regex_rules,
    repository_contracts as repository_contract_rules, runtime_bootstrap as runtime_bootstrap_rule,
    sql_inline as sql_inline_rule, structure, trivial_wrappers, ui_consistency,
    yagni as yagni_rules, yagni_call_index, yagni_concentration,
};

use std::ffi::OsString;
use std::process::ExitCode;

pub fn run(arguments: impl IntoIterator<Item = OsString>) -> ExitCode {
    match cli::parse(arguments) {
        Ok(cli::Command::Help) => {
            println!("{}", cli::usage());
            ExitCode::SUCCESS
        }
        Ok(cli::Command::Version) => {
            println!("cb {}", env!("CARGO_PKG_VERSION"));
            println!("runtime: Rust");
            ExitCode::SUCCESS
        }
        Ok(cli::Command::Summary(options)) => summary_exit(summary_command::execute(&options)),
        Ok(cli::Command::Baseline(options)) => match baseline_command::execute(&options) {
            Ok(baseline_command::BaselineOutcome::Success) => ExitCode::SUCCESS,
            Ok(baseline_command::BaselineOutcome::Empty) => ExitCode::from(1),
            Err(error) => {
                eprintln!("{error}");
                ExitCode::from(2)
            }
        },
        Ok(cli::Command::Fix(options)) => match fix_command::execute(&options) {
            Ok(fix_command::FixOutcome::Success) => ExitCode::SUCCESS,
            Ok(fix_command::FixOutcome::Empty) => ExitCode::from(1),
            Err(error) => {
                eprintln!("{error}");
                ExitCode::from(2)
            }
        },
        Ok(cli::Command::Quality(options, view)) => quality_exit(&options, view),
        Ok(cli::Command::Review(options, view)) => review_exit(&options, view),
        Ok(cli::Command::Update(options)) => match update_command::execute(&options) {
            Ok(update_command::UpdateOutcome::Success) => ExitCode::SUCCESS,
            Ok(update_command::UpdateOutcome::Refused) => ExitCode::from(2),
            Ok(update_command::UpdateOutcome::Failed(code)) => ExitCode::from(code),
            Err(error) => {
                eprintln!("{error}");
                ExitCode::from(2)
            }
        },
        Ok(cli::Command::ConfigFiles(options)) => match preview::execute(&options) {
            Ok(()) => ExitCode::SUCCESS,
            Err(error) => {
                eprintln!("{error}");
                ExitCode::from(2)
            }
        },
        Ok(cli::Command::Completions(shell)) => {
            completions_command::execute(&shell);
            ExitCode::SUCCESS
        }
        Ok(cli::Command::Dead(options)) => match dead_command::execute(&options) {
            Ok(dead_command::DeadOutcome::Success) => ExitCode::SUCCESS,
            Ok(dead_command::DeadOutcome::Empty) => ExitCode::from(1),
            Ok(dead_command::DeadOutcome::Findings) => ExitCode::from(2),
            Err(error) => {
                eprintln!("{error}");
                ExitCode::from(2)
            }
        },
        Ok(cli::Command::Graph(options)) => match graph_command::execute(&options) {
            Ok(graph_command::GraphOutcome::Success) => ExitCode::SUCCESS,
            Ok(graph_command::GraphOutcome::Empty) => ExitCode::from(1),
            Err(error) => {
                eprintln!("{error}");
                ExitCode::from(2)
            }
        },
        Ok(cli::Command::Rules(options)) => {
            if options.targets.is_empty() {
                match rules_command::execute(&options.common) {
                    Ok(()) => ExitCode::SUCCESS,
                    Err(error) => {
                        eprintln!("{error}");
                        ExitCode::from(2)
                    }
                }
            } else {
                repository_view_exit(Ok(explain_command::execute(&options)))
            }
        }
        Ok(cli::Command::Inspect(options, view)) => match view {
            cli::InspectView::Details => {
                repository_view_exit(repository_view_command::execute_inspect(&options))
            }
            cli::InspectView::Related => {
                repository_view_exit(repository_view_command::execute_related(&options))
            }
            cli::InspectView::Why => {
                repository_view_exit(repository_view_command::execute_why(&options))
            }
            cli::InspectView::Path => {
                repository_view_exit(repository_view_command::execute_path(&options))
            }
        },
        Ok(cli::Command::Config(options)) => match config_command::execute(&options) {
            Ok(()) => ExitCode::SUCCESS,
            Err(error) => {
                eprintln!("{error}");
                ExitCode::from(2)
            }
        },
        Ok(cli::Command::Doctor(options)) => match doctor_command::execute(&options) {
            Ok(()) => ExitCode::SUCCESS,
            Err(error) => {
                eprintln!("{error}");
                ExitCode::from(2)
            }
        },
        Ok(cli::Command::Duplication(options)) => {
            duplication_exit(duplication_command::execute(&options))
        }
        Ok(cli::Command::Init(options)) => match init_command::execute(&options) {
            Ok(init_command::InitOutcome::Created) => ExitCode::SUCCESS,
            Ok(init_command::InitOutcome::Exists) => ExitCode::from(1),
            Err(error) => {
                eprintln!("{error}");
                ExitCode::from(2)
            }
        },
        Err(error) => {
            if error.starts_with("Unknown Code Buster command:")
                || error == "--no-cache cannot be combined with --cache-dir"
            {
                eprintln!("{error}\n{}", cli::argument_usage());
            } else {
                eprintln!("{error}");
            }
            ExitCode::from(2)
        }
    }
}

fn review_exit(options: &cli::PreviewOptions, view: cli::ReviewView) -> ExitCode {
    match view {
        cli::ReviewView::Findings => {
            summary_exit(summary_command::execute_report(options, "review"))
        }
        cli::ReviewView::Plan => unit_exit(workflow_command::execute_plan(options)),
        cli::ReviewView::Actions => match workflow_command::execute_actions(options) {
            Ok(workflow_command::WorkflowOutcome::Success) => ExitCode::SUCCESS,
            Ok(workflow_command::WorkflowOutcome::Findings) => ExitCode::from(2),
            Err(error) => error_exit(error),
        },
    }
}

fn quality_exit(options: &cli::PreviewOptions, view: cli::QualityView) -> ExitCode {
    match view {
        cli::QualityView::Overview => match quality_command::execute_quality(options) {
            Ok(quality_command::QualityOutcome::Success) => ExitCode::SUCCESS,
            Ok(quality_command::QualityOutcome::Findings) => ExitCode::from(2),
            Err(error) => error_exit(error),
        },
        cli::QualityView::Score => unit_exit(quality_command::execute_score(options)),
        cli::QualityView::Complexity => match complexity_command::execute(options) {
            Ok(complexity_command::ComplexityOutcome::Success) => ExitCode::SUCCESS,
            Ok(complexity_command::ComplexityOutcome::Empty) => ExitCode::from(1),
            Ok(complexity_command::ComplexityOutcome::Findings) => ExitCode::from(2),
            Err(error) => error_exit(error),
        },
        cli::QualityView::Hotspots => match hotspots_command::execute(options) {
            Ok(hotspots_command::HotspotsOutcome::Success) => ExitCode::SUCCESS,
            Ok(hotspots_command::HotspotsOutcome::Empty) => ExitCode::from(1),
            Err(error) => error_exit(error),
        },
        cli::QualityView::Structure => match structure_command::execute(options) {
            Ok(structure_command::StructureOutcome::Success) => ExitCode::SUCCESS,
            Ok(structure_command::StructureOutcome::Empty) => ExitCode::from(1),
            Ok(structure_command::StructureOutcome::Findings) => ExitCode::from(2),
            Err(error) => error_exit(error),
        },
    }
}

fn duplication_exit(result: Result<duplication_command::DuplicationOutcome, String>) -> ExitCode {
    match result {
        Ok(duplication_command::DuplicationOutcome::Success) => ExitCode::SUCCESS,
        Ok(duplication_command::DuplicationOutcome::Empty) => ExitCode::from(1),
        Ok(duplication_command::DuplicationOutcome::Findings) => ExitCode::from(2),
        Err(error) => error_exit(error),
    }
}

fn unit_exit(result: Result<(), String>) -> ExitCode {
    match result {
        Ok(()) => ExitCode::SUCCESS,
        Err(error) => error_exit(error),
    }
}

fn error_exit(error: String) -> ExitCode {
    eprintln!("{error}");
    ExitCode::from(2)
}

fn summary_exit(result: Result<summary_command::SummaryOutcome, String>) -> ExitCode {
    match result {
        Ok(summary_command::SummaryOutcome::Success) => ExitCode::SUCCESS,
        Ok(summary_command::SummaryOutcome::Empty) => ExitCode::from(1),
        Ok(summary_command::SummaryOutcome::Findings) => ExitCode::from(2),
        Err(error) => {
            eprintln!("{error}");
            ExitCode::from(2)
        }
    }
}

fn repository_view_exit(
    result: Result<repository_view_command::RepositoryViewOutcome, String>,
) -> ExitCode {
    match result {
        Ok(repository_view_command::RepositoryViewOutcome::Success) => ExitCode::SUCCESS,
        Ok(repository_view_command::RepositoryViewOutcome::Findings) => ExitCode::from(2),
        Ok(repository_view_command::RepositoryViewOutcome::NotFound) => ExitCode::from(1),
        Ok(repository_view_command::RepositoryViewOutcome::Usage) => ExitCode::from(64),
        Err(error) => {
            eprintln!("{error}");
            ExitCode::from(2)
        }
    }
}