1use std::fmt;
2
3pub use crate::_internal::analysis::evidence::{
4 EvidenceCode, EvidenceLocation, EvidenceRecord, EvidenceScope,
5};
6pub use crate::_internal::analysis::outcome::AnalysisOutcome;
7pub use crate::_internal::analysis::state::AnalysisState;
8pub use crate::_internal::db::cache::DbCache;
9pub use crate::_internal::engine::config::Config;
10pub use crate::_internal::engine::engine::SafeMigrateEngine;
11pub use crate::_internal::report::reporter::Reporter;
12pub use crate::_internal::report::violations::ReportFinding;
13pub use crate::_internal::rules::RuleCapability;
14
15#[derive(Debug)]
17pub enum AnalysisError {
18 InvalidCache(String),
19 Parse(Vec<String>),
20}
21
22impl fmt::Display for AnalysisError {
23 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
24 match self {
25 Self::InvalidCache(error) => write!(formatter, "invalid cache: {error}"),
26 Self::Parse(errors) => write!(formatter, "analysis failed: {}", errors.join("; ")),
27 }
28 }
29}
30
31impl std::error::Error for AnalysisError {}
32
33pub fn analyze(
38 config: Config,
39 filename: impl Into<String>,
40 sql: impl Into<String>,
41 cache: DbCache,
42) -> Result<AnalysisOutcome<ReportFinding>, AnalysisError> {
43 analyze_chain(config, &[(filename.into(), sql.into())], cache)
44}
45
46pub fn analyze_chain(
48 config: Config,
49 files: &[(String, String)],
50 cache: DbCache,
51) -> Result<AnalysisOutcome<ReportFinding>, AnalysisError> {
52 let mut state = AnalysisState::try_new(cache).map_err(AnalysisError::InvalidCache)?;
53 let engine = SafeMigrateEngine::new(config);
54 engine
55 .analyze_chain_outcome_with_locations(files, &mut state)
56 .map_err(AnalysisError::Parse)
57}