use std::path::{Path, PathBuf};
use serde_json::Value;
use xuanji::{Outcome, Violation};
use crate::driver::run_boundaries;
use crate::dsl::VisibilityBoundary;
use crate::emit::{SingleModuleViolationContext, push_single_module_violations};
use crate::errors::unknown_module_error;
use crate::file_scope::{over_each_unit, resolve_crate_units};
use crate::finding::{SemanticFact, sort_faceted_facts};
use crate::module_resolve::resolve_module_items_with_files;
use crate::syn_util::item_observation;
pub fn check_visibility(boundaries: &[VisibilityBoundary], manifest_path: &Path) -> Outcome {
run_boundaries(boundaries, manifest_path, check_visibility_boundary)
}
pub(crate) fn check_visibility_boundary(
metadata: &Value,
boundary: &VisibilityBoundary,
violations: &mut Vec<Violation>,
) -> Result<(), String> {
let (_package, units) = resolve_crate_units(metadata, &boundary.crate_package)?;
over_each_unit(
&units,
&unknown_module_error(&boundary.module, &boundary.crate_package),
|root_file, src_dir, unit| {
let findings = visibility_findings(
src_dir,
root_file,
&boundary.module,
&boundary.crate_package,
boundary.ceiling().rank(),
)?;
push_single_module_violations(
violations,
SingleModuleViolationContext {
module: &boundary.module,
rule: boundary.ceiling().rule(),
rule_key: boundary.rule_key(),
reason: &boundary.reason,
severity: boundary.severity,
anchor: boundary.anchor(),
crate_package: &boundary.crate_package,
unit,
},
findings,
);
Ok(())
},
)
}
pub(crate) fn visibility_findings(
src_dir: &Path,
root_file: &Path,
module: &str,
crate_package: &str,
ceiling_rank: u8,
) -> Result<Vec<(SemanticFact, PathBuf)>, String> {
let items_with_files =
resolve_module_items_with_files(src_dir, root_file, module, crate_package)?;
let mut findings: Vec<(SemanticFact, PathBuf)> = items_with_files
.iter()
.flat_map(|(item, file, _branch)| {
item_observation(item, ceiling_rank)
.into_iter()
.map(move |obs| (obs, file))
})
.map(|((visibility, item_kind, item_name), file)| {
(
SemanticFact::Visibility {
visibility,
item_kind,
item_name,
},
file.clone(),
)
})
.collect();
sort_faceted_facts(&mut findings)?;
Ok(findings)
}