#![cfg_attr(coverage_nightly, coverage(off))]
use super::types::*;
use anyhow::Result;
use async_trait::async_trait;
use std::path::Path;
use std::process::Command;
#[async_trait]
pub trait SignalCollector: Send + Sync {
fn source(&self) -> SignalSource;
async fn collect(&self, project_path: &Path) -> Result<Vec<SignalEvidence>>;
}
pub struct RustcCollector;
pub struct ClippyCollector;
pub struct TestCollector;
include!("signal_collector_impls.rs");
pub struct AggregatedCollector {
collectors: Vec<Box<dyn SignalCollector>>,
}
impl AggregatedCollector {
pub fn new() -> Self {
Self {
collectors: vec![
Box::new(RustcCollector),
Box::new(ClippyCollector),
Box::new(TestCollector),
],
}
}
pub fn add_collector(&mut self, collector: Box<dyn SignalCollector>) {
self.collectors.push(collector);
}
pub fn collector_count(&self) -> usize {
self.collectors.len()
}
pub async fn collect_all(&self, project_path: &Path) -> Result<Vec<SignalEvidence>> {
let mut all_signals = Vec::new();
for collector in &self.collectors {
match collector.collect(project_path).await {
Ok(signals) => all_signals.extend(signals),
Err(e) => {
eprintln!("Warning: {:?} collector failed: {}", collector.source(), e);
}
}
}
Ok(all_signals)
}
pub fn signals_to_defects(&self, signals: Vec<SignalEvidence>) -> Vec<DefectReport> {
let mut defects: Vec<DefectReport> = Vec::new();
for signal in signals {
let category = signal
.error_code
.as_ref()
.and_then(|code| DefectCategory::from_rustc_error(code))
.unwrap_or(DefectCategory::Configuration);
let severity = match signal.source {
SignalSource::Rustc => Severity::Critical,
SignalSource::CargoTest => Severity::High,
SignalSource::Clippy => Severity::Medium,
_ => Severity::Low,
};
let mut defect = DefectReport::new(
category,
severity,
CodeLocation {
file_path: std::path::PathBuf::from("unknown"),
line: 0,
column: None,
span_end_line: None,
},
);
defect.add_signal(signal);
defects.push(defect);
}
defects
}
}
impl Default for AggregatedCollector {
fn default() -> Self {
Self::new()
}
}
include!("signal_collector_tests.rs");
include!("signal_collector_tests_types.rs");