use pedant_syntax::go::GoScopeFact;
use crate::resolution::go::binding_fact::GoBindingRecord;
use crate::resolution::go::facts::GoSourceFacts;
use crate::resolution::identity::index_of;
fn chain(facts: &GoSourceFacts, scope: u32) -> Box<[u32]> {
let mut held = Vec::new();
let mut current = Some(scope);
while let Some(index) = current.filter(|_| held.len() < facts.scopes().len()) {
held.push(index);
current = facts
.scopes()
.get(index_of(index))
.and_then(GoScopeFact::parent);
}
held.into_boxed_slice()
}
pub(super) fn binding<'a>(
facts: &'a GoSourceFacts,
at: (u32, usize),
name: &str,
) -> Option<&'a GoBindingRecord> {
let (scope, offset) = at;
let held = chain(facts, scope);
facts
.bindings()
.iter()
.filter(|bound| bound.name() == name && bound.span().start_byte() < offset)
.filter_map(|bound| depth(&held, bound.scope()).map(|depth| (depth, bound)))
.min_by_key(|(depth, _)| *depth)
.map(|(_, bound)| bound)
}
fn depth(held: &[u32], scope: u32) -> Option<usize> {
held.iter().position(|open| *open == scope)
}