use crate::graph::{FragUsing, Fragment};
use std::collections::{HashMap, HashSet};
pub(super) fn namespace_encloses(outer: &str, inner: &str) -> bool {
inner
.strip_prefix(outer)
.is_some_and(|rest| rest.starts_with('.'))
}
pub(super) fn score_candidate(
def_namespace: &str,
ref_namespace: &str,
usings: &HashSet<String>,
) -> u8 {
if def_namespace == ref_namespace {
return 3;
}
if usings.contains(def_namespace) {
return 2;
}
1
}
pub(super) struct FileContext {
pub(super) usings: HashSet<String>,
pub(super) aliases: HashMap<String, String>,
}
pub(super) fn build_file_contexts(
fragments_by_file: &[(String, Fragment)],
repo_wide: &GlobalUsings,
by_unit: Option<UnitGlobals<'_>>,
) -> HashMap<String, FileContext> {
let mut contexts = HashMap::new();
let empty: GlobalUsings = (HashSet::new(), HashMap::new());
for (file, frag) in fragments_by_file {
let seed = match by_unit {
Some((unit_of_file, by_unit)) => match unit_of_file.get(file).copied().flatten() {
Some(u) => by_unit.get(&u).unwrap_or(&empty),
None => repo_wide,
},
None => repo_wide,
};
let mut usings = seed.0.clone();
let mut aliases = seed.1.clone();
for u in &frag.usings {
match u {
FragUsing::Alias { alias, target, .. } => {
aliases.insert(alias.clone(), target.clone());
}
FragUsing::Plain { text, .. } => {
usings.insert(text.clone());
}
}
}
contexts.insert(file.clone(), FileContext { usings, aliases });
}
contexts
}
type UnitGlobals<'a> = (
&'a HashMap<String, Option<usize>>,
&'a HashMap<usize, GlobalUsings>,
);
type GlobalUsings = (HashSet<String>, HashMap<String, String>);
pub(super) fn collect_global_usings_by_unit(
fragments_by_file: &[(String, Fragment)],
unit_of_file: &HashMap<String, Option<usize>>,
) -> (GlobalUsings, HashMap<usize, GlobalUsings>) {
let mut repo_wide: GlobalUsings = (HashSet::new(), HashMap::new());
let mut by_unit: HashMap<usize, GlobalUsings> = HashMap::new();
for (file, frag) in fragments_by_file {
let unit = unit_of_file.get(file).copied().flatten();
for u in &frag.usings {
match u {
FragUsing::Alias {
alias,
target,
global,
} => {
if *global {
repo_wide
.1
.entry(alias.clone())
.or_insert_with(|| target.clone());
if let Some(idx) = unit {
by_unit
.entry(idx)
.or_default()
.1
.entry(alias.clone())
.or_insert_with(|| target.clone());
}
}
}
FragUsing::Plain { text, global } => {
if *global {
repo_wide.0.insert(text.clone());
if let Some(idx) = unit {
by_unit.entry(idx).or_default().0.insert(text.clone());
}
}
}
}
}
}
(repo_wide, by_unit)
}