refactor: extract module_edges() to CodeGraph domain — removes duplication from Mermaid and D2 renderers
This commit is contained in:
@@ -278,4 +278,72 @@ impl CodeGraph {
|
||||
relationships: filtered_relationships,
|
||||
}
|
||||
}
|
||||
|
||||
/// Compute module-to-module edges with relationship counts.
|
||||
///
|
||||
/// Handles three cases:
|
||||
/// - Direct module-name edges injected by `merge_project_deps_as_module_edges`
|
||||
/// - Type-level composition/inheritance relationships resolved to their modules
|
||||
/// - Import relationships resolved via file-stem → module mapping
|
||||
pub fn module_edges(&self) -> HashMap<(String, String), usize> {
|
||||
let mut name_to_module: HashMap<&str, &str> = HashMap::new();
|
||||
let mut file_to_module: HashMap<String, String> = HashMap::new();
|
||||
let mut modules: HashSet<String> = HashSet::new();
|
||||
|
||||
for el in &self.elements {
|
||||
if let Some(m) = el.module() {
|
||||
modules.insert(m.as_str().to_string());
|
||||
name_to_module.insert(el.qualified_name(), m.as_str());
|
||||
name_to_module.insert(el.name(), m.as_str());
|
||||
|
||||
let file_stem = std::path::Path::new(el.file_path().as_str())
|
||||
.file_stem()
|
||||
.and_then(|s| s.to_str())
|
||||
.unwrap_or_default()
|
||||
.to_string();
|
||||
if !file_stem.is_empty() {
|
||||
file_to_module.insert(file_stem, m.as_str().to_string());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let mut edges: HashMap<(String, String), usize> = HashMap::new();
|
||||
|
||||
for rel in &self.relationships {
|
||||
match rel.kind() {
|
||||
RelationshipKind::Import => {
|
||||
let source_mod = file_to_module.get(rel.source());
|
||||
let target_top = rel.target().split('.').next().unwrap_or("");
|
||||
let target_mod = ModuleName::capitalize(target_top);
|
||||
if let Some(src) = source_mod
|
||||
&& modules.contains(&target_mod)
|
||||
&& *src != target_mod
|
||||
{
|
||||
*edges.entry((src.clone(), target_mod)).or_insert(0) += 1;
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
// Direct module-to-module edge (injected by merge_project_deps)
|
||||
if modules.contains(rel.source())
|
||||
&& modules.contains(rel.target())
|
||||
&& rel.source() != rel.target()
|
||||
{
|
||||
*edges
|
||||
.entry((rel.source().to_string(), rel.target().to_string()))
|
||||
.or_insert(0) += 1;
|
||||
continue;
|
||||
}
|
||||
let src_mod = name_to_module.get(rel.source()).copied();
|
||||
let tgt_mod = name_to_module.get(rel.target()).copied();
|
||||
if let (Some(s), Some(t)) = (src_mod, tgt_mod)
|
||||
&& s != t
|
||||
{
|
||||
*edges.entry((s.to_string(), t.to_string())).or_insert(0) += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
edges
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user