use scip::types::{self as scip_types};
pub(super) fn short_name(scip_symbol: &str) -> &str {
let trimmed = scip_symbol.trim_end_matches(|c: char| !c.is_alphanumeric() && c != '_');
trimmed.rsplit(['/', '.', '#']).next().unwrap_or(trimmed)
}
pub(super) fn is_definition(occ: &scip_types::Occurrence) -> bool {
occ.symbol_roles & 1 != 0
}
pub(super) fn parse_range(occ: &scip_types::Occurrence) -> (usize, usize, usize, usize) {
let r = &occ.range;
match r.len() {
3 => (r[0] as usize, r[1] as usize, r[0] as usize, r[2] as usize),
4 => (r[0] as usize, r[1] as usize, r[2] as usize, r[3] as usize),
_ => (0, 0, 0, 0),
}
}
pub(super) fn is_function_like_symbol(scip_symbol: &str) -> bool {
scip_symbol.contains("()")
}
pub(super) fn body_end_line(
doc: &scip_types::Document,
start_line: usize,
occ_end_line: usize,
) -> Option<usize> {
let mut sibling_starts: Vec<usize> = doc
.occurrences
.iter()
.filter(|occ| is_definition(occ))
.map(|occ| parse_range(occ).0)
.filter(|line| *line > start_line)
.collect();
sibling_starts.sort_unstable();
let next_def = sibling_starts.first().copied();
let sibling_estimate = next_def.map(|n| n.saturating_sub(1));
match (sibling_estimate, occ_end_line) {
(Some(est), occ) if occ > est => Some(occ),
(Some(est), _) if est > start_line => Some(est),
(None, occ) if occ > start_line => Some(occ),
_ => None,
}
}