use std::sync::Arc;
use fxhash::FxHashMap;
use petgraph::{algo::has_path_connecting, graph::NodeIndex, Graph};
use super::{
rir::Item,
ty::{self},
};
use crate::symbol::DefId;
#[derive(Debug)]
pub struct TypeGraph {
graph: Graph<DefId, ()>,
node_map: FxHashMap<DefId, NodeIndex>,
}
impl TypeGraph {
pub fn from_items(items: impl Iterator<Item = (DefId, Arc<Item>)> + Clone) -> Self {
let mut graph: Graph<DefId, ()> = Graph::new();
let mut node_map = FxHashMap::default();
items.clone().for_each(|(def_id, _)| {
node_map.insert(def_id, graph.add_node(def_id));
});
items.for_each(|(def_id, item)| {
let idx = node_map[&def_id];
match &*item {
Item::Message(s) => s.fields.iter().for_each(|f| {
if let ty::Path(p) = &f.ty.kind {
graph.add_edge(idx, node_map[&p.did], ());
}
}),
Item::Enum(e) => {
e.variants.iter().flat_map(|v| &v.fields).for_each(|ty| {
if let ty::Path(p) = &ty.kind {
graph.add_edge(idx, node_map[&p.did], ());
}
});
}
Item::NewType(t) => {
if let ty::Path(p) = &t.ty.kind {
graph.add_edge(idx, node_map[&p.did], ());
}
}
_ => {}
};
});
Self { graph, node_map }
}
pub fn is_nested(&self, a: DefId, b: DefId) -> bool {
let a = self.node_map[&a];
let b = self.node_map[&b];
has_path_connecting(&self.graph, a, b, None)
}
}