repopilot 0.13.0

Local-first CLI for repository audit, architecture risk detection, baseline tracking, and CI-friendly code review.
Documentation
use crate::audits::code_quality::sanitize::{sanitize_c_style, sanitize_python_line};
use crate::audits::traits::FileAudit;
use crate::findings::types::Finding;
use crate::knowledge::language::language_id_for_name;
use crate::scan::config::ScanConfig;
use crate::scan::facts::FileFacts;
use std::path::Path;

pub struct LanguageRiskAudit;

impl FileAudit for LanguageRiskAudit {
    fn audit(&self, file: &FileFacts, _config: &ScanConfig) -> Vec<Finding> {
        let Some(content) = file
            .content
            .as_deref()
            .filter(|content| !content.is_empty())
        else {
            return vec![];
        };

        let Some(language_id) = file.language.as_deref().and_then(language_id_for_name) else {
            return vec![];
        };

        detect_language_risks(language_id, content, &file.path, file)
    }
}

fn detect_language_risks(
    language_id: &str,
    content: &str,
    path: &Path,
    file: &FileFacts,
) -> Vec<Finding> {
    let mut findings = Vec::new();
    let mut in_block_comment = false;

    for (line_index, raw_line) in content.lines().enumerate() {
        let sanitized = if language_id == "python" {
            match sanitize_python_line(raw_line) {
                Some(s) => s,
                None => continue,
            }
        } else {
            sanitize_c_style(raw_line, &mut in_block_comment)
        };

        let trimmed = sanitized.trim();
        if trimmed.is_empty() {
            continue;
        }

        emit_findings_for_line(
            language_id,
            trimmed,
            path,
            raw_line,
            line_index,
            file,
            &mut findings,
        );
    }

    findings
}

mod pattern;

use self::pattern::emit_findings_for_line;

#[cfg(test)]
mod tests;