use std::rc::Rc;
use crate::graph::extend_edges_from_names;
use crate::ir::facts::{ImplFact, IrSpan};
use crate::ir::type_introspection::collect_signature_type_names_into;
pub(super) fn impl_fact(
node: &syn::ItemImpl,
position: (&Rc<str>, IrSpan, Box<[Rc<str>]>),
) -> ImplFact {
let (self_name, span, cfg_predicates) = position;
let trait_name = trait_name(node);
ImplFact {
self_type: Rc::clone(self_name),
edges: edges(node, self_name, trait_name.as_deref()),
trait_name,
span,
cfg_predicates,
}
}
fn trait_name(node: &syn::ItemImpl) -> Option<Box<str>> {
node.trait_
.as_ref()
.and_then(|(_, path, _)| path.segments.last())
.map(|segment| segment.ident.to_string().into_boxed_str())
}
fn edges(
node: &syn::ItemImpl,
self_name: &Rc<str>,
trait_name: Option<&str>,
) -> Box<[(Rc<str>, Rc<str>)]> {
let mut edges: Vec<(Rc<str>, Rc<str>)> = trait_name
.map(|named| (Rc::clone(self_name), Rc::from(named)))
.into_iter()
.collect();
let mut names = Vec::new();
for item in &node.items {
let syn::ImplItem::Fn(method) = item else {
continue;
};
names.clear();
collect_signature_type_names_into(&method.sig, &mut names);
extend_edges_from_names(self_name, &names, &mut edges);
}
edges.into_boxed_slice()
}