use std::path::Path;
use std::string::ToString;
use crate::analysis::AnalysisResult;
use crate::analysis::analyze;
use crate::analyzer::LanguageAnalyzer;
use crate::cli::cli_error::CliError;
use crate::cli::cli_error::CliResult;
use crate::cli::cli_overrides::CliOverrides;
use crate::cli::output_format::OutputFormat;
use crate::config::Config;
use crate::output::reporter::Reporter;
use crate::scanner::ScanConfig;
use crate::scanner::scan_files;
pub struct AnalysisOutput {
pub config: Config,
pub result: AnalysisResult,
pub reporter: Box<dyn Reporter>,
}
impl AnalysisOutput {
pub fn produce(
analyzer: &dyn LanguageAnalyzer,
root: &Path,
format: OutputFormat,
overrides: &CliOverrides,
) -> CliResult<Self> {
Self::from_config(analyzer, root, format, Self::configure(root, overrides)?)
}
pub fn produce_ignoring_baseline(
analyzer: &dyn LanguageAnalyzer,
root: &Path,
format: OutputFormat,
overrides: &CliOverrides,
) -> CliResult<Self> {
let mut config = Self::configure(root, overrides)?;
let named = config.baseline.take();
let output = Self::from_config(analyzer, root, format, config)?;
Ok(Self {
config: Config {
baseline: named,
..output.config
},
..output
})
}
fn configure(root: &Path, overrides: &CliOverrides) -> CliResult<Config> {
Config::load(root)
.and_then(|config| overrides.apply_to(config))
.map_err(|e| CliError::InvalidConfig(e.to_string()))
}
fn from_config(
analyzer: &dyn LanguageAnalyzer,
root: &Path,
format: OutputFormat,
config: Config,
) -> CliResult<Self> {
let scan_config = ScanConfig::new(config.root.clone())
.with_excludes(config.exclude.clone())
.with_extensions(
analyzer
.file_extensions()
.iter()
.map(ToString::to_string)
.collect(),
);
let files = scan_files(&scan_config);
if files.is_empty() {
return Err(CliError::NoSourceFiles(config.root));
}
let result = analyze(analyzer, &files, &config)?;
let reporter = format.reporter(Some(root));
Ok(Self {
config,
result,
reporter,
})
}
}