use std::collections::BTreeMap;
use pedant_syntax::go::GoImportForm;
use crate::resolution::go::facts::GoSourceFacts;
use crate::resolution::go::import_fact::GoImportRecord;
use super::corpus::Corpus;
#[derive(Clone, Copy)]
pub(super) struct ImportTarget<'a> {
pub(super) unit: Option<usize>,
pub(super) path: &'a str,
}
pub(super) struct FileImports<'a> {
named: BTreeMap<&'a str, ImportTarget<'a>>,
dotted: Box<[ImportTarget<'a>]>,
}
impl<'a> FileImports<'a> {
pub(super) fn of(corpus: &Corpus<'a>, facts: &'a GoSourceFacts) -> Self {
Self {
named: facts
.imports()
.iter()
.filter_map(|import| named_binding(corpus, import))
.collect(),
dotted: facts
.imports()
.iter()
.filter(|import| import.form() == GoImportForm::Dot)
.map(|import| target(corpus, import))
.collect(),
}
}
pub(super) fn named(&self, name: &str) -> Option<ImportTarget<'a>> {
self.named.get(name).copied()
}
pub(super) fn dotted(&self) -> &[ImportTarget<'a>] {
&self.dotted
}
}
fn named_binding<'a>(
corpus: &Corpus<'a>,
import: &'a GoImportRecord,
) -> Option<(&'a str, ImportTarget<'a>)> {
let found = target(corpus, import);
let name = match import.form() {
GoImportForm::Named => found
.unit
.and_then(|unit| corpus.unit(unit))
.map(|unit| unit.package_name())
.or_else(|| import.local_name()),
GoImportForm::Aliased => import.local_name(),
GoImportForm::Dot | GoImportForm::Blank => None,
};
name.map(|name| (name, found))
}
pub(super) fn target<'a>(corpus: &Corpus<'_>, import: &'a GoImportRecord) -> ImportTarget<'a> {
ImportTarget {
unit: corpus.package(import.path()),
path: import.path(),
}
}