use std::collections::BTreeMap;
use std::sync::Arc;
use crate::resolution::go::condition::GoBuildCondition;
use crate::resolution::go::snapshot::GoResolutionSnapshot;
use crate::resolution::go::source::GoSource;
use crate::resolution::go::unit::{GoPackageContext, GoResolutionUnit};
use super::error::GoResolutionError;
use super::imports::FileImports;
#[derive(Clone, Copy)]
pub(super) struct UnitSource<'a> {
pub(super) path: &'a Arc<str>,
pub(super) source: &'a GoSource,
pub(super) imports: &'a FileImports<'a>,
}
pub(super) struct Corpus<'a> {
snapshot: &'a GoResolutionSnapshot,
packages: BTreeMap<&'a str, usize>,
sources: BTreeMap<&'a str, &'a GoSource>,
imports: BTreeMap<&'a str, FileImports<'a>>,
}
impl<'a> Corpus<'a> {
pub(super) fn of(snapshot: &'a GoResolutionSnapshot) -> Self {
let mut corpus = Self {
snapshot,
packages: snapshot
.units()
.iter()
.enumerate()
.filter(|(_, unit)| unit.context() == GoPackageContext::Production)
.map(|(index, unit)| (unit.import_path(), index))
.collect(),
sources: snapshot
.sources()
.iter()
.map(|source| (source.path(), source))
.collect(),
imports: BTreeMap::new(),
};
corpus.imports = read_imports(&corpus);
corpus
}
pub(super) fn units(&self) -> &'a [GoResolutionUnit] {
self.snapshot.units()
}
pub(super) fn unit(&self, index: usize) -> Option<&'a GoResolutionUnit> {
self.snapshot.units().get(index)
}
pub(super) fn package(&self, import_path: &str) -> Option<usize> {
self.packages.get(import_path).copied()
}
pub(super) fn sources_of<'held>(
&'held self,
unit: &'held GoResolutionUnit,
) -> Result<Box<[UnitSource<'held>]>, GoResolutionError> {
unit.sources()
.iter()
.map(|path| self.held(unit, path))
.collect()
}
fn held<'held>(
&'held self,
unit: &GoResolutionUnit,
path: &'held Arc<str>,
) -> Result<UnitSource<'held>, GoResolutionError> {
let stated = self
.sources
.get(&**path)
.copied()
.zip(self.imports.get(&**path));
let (source, imports) = stated.ok_or_else(|| GoResolutionError::UnitMapping {
unit: unit.id().index(),
reason: Box::from("a source of this package context is not held by the snapshot"),
})?;
Ok(UnitSource {
path,
source,
imports,
})
}
}
fn read_imports<'a>(corpus: &Corpus<'a>) -> BTreeMap<&'a str, FileImports<'a>> {
corpus
.sources
.iter()
.map(|(path, source)| (*path, FileImports::of(corpus, source.facts())))
.collect()
}
pub(super) fn conditional(source: &GoSource) -> bool {
source
.conditions()
.iter()
.any(|condition| !matches!(condition, GoBuildCondition::TestContext))
}