use std::collections::BTreeMap;
use std::collections::BTreeSet;
use std::fs;
use std::path::Path;
use std::path::PathBuf;
use anyhow::Context;
use anyhow::Result;
use super::schema::StoredFinding;
use super::schema::StoredPubUseFixFact;
use super::schema::UseSite;
use super::schema::UseSiteReference;
use super::visibility_constraint::StoredVisibilityConstraint;
use crate::compiler::constants::FINDINGS_DIR_NAME;
#[derive(Default)]
pub(in crate::compiler) struct FindingsSink {
pub findings: Vec<StoredFinding>,
pub visibility_constraints: Vec<StoredVisibilityConstraint>,
pub pub_use_fix_facts: Vec<StoredPubUseFixFact>,
pub use_sites: UseSiteIndex,
}
#[derive(Default)]
pub(in crate::compiler) struct UseSiteIndex(BTreeMap<String, BTreeMap<String, UseSiteReference>>);
impl UseSiteIndex {
pub(in crate::compiler) fn insert(
&mut self,
target_def_path: String,
caller_module_def_path: String,
reference: UseSiteReference,
) {
let recorded = self
.0
.entry(target_def_path)
.or_default()
.entry(caller_module_def_path)
.or_insert(reference);
if matches!(
(*recorded, reference),
(_, UseSiteReference::Named)
| (
UseSiteReference::PrivateImport | UseSiteReference::RestrictedImport,
UseSiteReference::ThroughSignature
)
| (UseSiteReference::DeclarationInterface, _)
) {
*recorded = reference;
}
}
pub(in crate::compiler) fn callers(&self, target_def_path: &str) -> BTreeSet<String> {
self.0
.get(target_def_path)
.map(|callers| callers.keys().cloned().collect())
.unwrap_or_default()
}
pub(in crate::compiler) fn into_use_sites(self) -> Vec<UseSite> {
self.0
.into_iter()
.flat_map(|(target_def_path, callers)| {
callers
.into_iter()
.map(move |(caller_module_def_path, reference)| UseSite {
target_def_path: target_def_path.clone(),
caller_module_def_path,
reference,
})
})
.collect()
}
}
pub(in crate::compiler) fn prepare_findings_dir(target_directory: &Path) -> Result<PathBuf> {
let findings_dir = target_directory.join(FINDINGS_DIR_NAME);
fs::create_dir_all(&findings_dir).with_context(|| {
format!(
"failed to create findings directory {}",
findings_dir.display()
)
})?;
Ok(findings_dir)
}