xbp-analysis 10.57.0

Language-agnostic static analysis (error-handling / Aspirator-style) for XBP
Documentation
//! Analysis request / configuration domain objects.

use super::rule::RuleSelection;
use super::types::{ApprovedPattern, LanguageId, Severity, Suppression};
use serde::{Deserialize, Serialize};
use std::path::PathBuf;

#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum OutputFormat {
    Terminal,
    Json,
    Sarif,
    GithubActions,
}

impl OutputFormat {
    pub fn parse(s: &str) -> Option<Self> {
        match s.to_ascii_lowercase().as_str() {
            "terminal" | "text" | "human" => Some(Self::Terminal),
            "json" => Some(Self::Json),
            "sarif" => Some(Self::Sarif),
            "github" | "github-actions" | "gha" => Some(Self::GithubActions),
            _ => None,
        }
    }
}

#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct AnalysisConfig {
    pub languages: Vec<LanguageId>,
    pub rules: RuleSelection,
    pub path_exclusions: Vec<String>,
    pub generated_exclusions: Vec<String>,
    pub suppressions: Vec<Suppression>,
    pub approved_patterns: Vec<ApprovedPattern>,
    pub min_severity: Option<Severity>,
    pub adapter_config: serde_json::Value,
}

impl AnalysisConfig {
    pub fn default_for_rust() -> Self {
        Self {
            languages: vec![LanguageId::rust()],
            rules: RuleSelection::default(),
            path_exclusions: vec![
                "**/target/**".into(),
                "**/node_modules/**".into(),
                "**/.git/**".into(),
                "**/vendor/**".into(),
            ],
            generated_exclusions: vec![
                "**/*_generated.rs".into(),
                "**/generated/**".into(),
                "**/*.pb.rs".into(),
            ],
            suppressions: Vec::new(),
            approved_patterns: Vec::new(),
            min_severity: None,
            adapter_config: serde_json::json!({}),
        }
    }
}

#[derive(Debug, Clone)]
pub struct AnalysisRequest {
    pub root: PathBuf,
    pub paths: Vec<PathBuf>,
    pub config: AnalysisConfig,
    pub format: OutputFormat,
    pub apply_fixes: bool,
    pub workspace: bool,
    pub language_filter: Option<LanguageId>,
}

impl AnalysisRequest {
    pub fn new(root: impl Into<PathBuf>) -> Self {
        Self {
            root: root.into(),
            paths: Vec::new(),
            config: AnalysisConfig::default_for_rust(),
            format: OutputFormat::Terminal,
            apply_fixes: false,
            workspace: false,
            language_filter: None,
        }
    }
}