refactor: five architectural deepening improvements
Candidate 1 (NormalizedGraph): qualify→resolve→filter is now a single
named operation returning a distinct type; raw CodeGraph cannot call
module_edges/subgraph_by_module — pipeline order enforced at compile time.
Candidate 2 (Use cases): GenerateDiagram, CheckFreshness, DiffDiagram
extracted to application/src/use_cases/; presentation is now a thin CLI
dispatcher (~100 lines less, three fewer local functions).
Candidate 3 (ExtractionContext): shared accumulator for both Rust and
Python extractors replaces parallel Vec<> + 4-arg passing chains.
Candidate 4 (ModuleAssignment): ModuleName::assign() returns
ModuleAssignment { Explicit | Inferred | Unresolved } instead of Option,
callers can distinguish resolution strategies.
Candidate 5 (SplitRenderer): append_cross_module_deps removed from
DiagramRenderer port; replaced by render_for_module() default impl —
port interface now reflects what all renderers actually share.
This commit is contained in:
@@ -226,42 +226,36 @@ impl DiagramRenderer for MermaidRenderer {
|
||||
Ok(RenderOutput::single(file))
|
||||
}
|
||||
|
||||
fn append_cross_module_deps(
|
||||
fn render_for_module(
|
||||
&self,
|
||||
content: &str,
|
||||
subgraph: &CodeGraph,
|
||||
module: &ModuleName,
|
||||
deps: &[(ModuleName, usize)],
|
||||
) -> String {
|
||||
if deps.is_empty() {
|
||||
return content.to_string();
|
||||
}
|
||||
|
||||
let src_id = format!(
|
||||
"{}_module",
|
||||
module.as_str().to_lowercase().replace('-', "_")
|
||||
);
|
||||
let mut extra = format!(
|
||||
" class {src_id}[\"{}\"] {{\n <<module>>\n }}\n",
|
||||
module.as_str()
|
||||
);
|
||||
|
||||
for (dep_mod, count) in deps {
|
||||
let dep_id = format!(
|
||||
"{}_module",
|
||||
dep_mod.as_str().to_lowercase().replace('-', "_")
|
||||
cross_deps: &[(ModuleName, usize)],
|
||||
) -> Result<RenderOutput, DomainError> {
|
||||
let base = self.render_class_diagram(subgraph);
|
||||
let content = if cross_deps.is_empty() {
|
||||
base
|
||||
} else {
|
||||
let src_id = format!("{}_module", module.as_str().to_lowercase().replace('-', "_"));
|
||||
let mut extra = format!(
|
||||
" class {src_id}[\"{}\"] {{\n <<module>>\n }}\n",
|
||||
module.as_str()
|
||||
);
|
||||
extra.push_str(&format!(
|
||||
" class {dep_id}[\"{}\"] {{\n <<module>>\n }}\n",
|
||||
dep_mod.as_str()
|
||||
));
|
||||
let label = if *count == 1 {
|
||||
"1 dep".to_string()
|
||||
} else {
|
||||
format!("{count} deps")
|
||||
};
|
||||
extra.push_str(&format!(" {src_id} --> {dep_id} : {label}\n"));
|
||||
}
|
||||
|
||||
format!("{content}\n{extra}")
|
||||
for (dep_mod, count) in cross_deps {
|
||||
let dep_id = format!(
|
||||
"{}_module",
|
||||
dep_mod.as_str().to_lowercase().replace('-', "_")
|
||||
);
|
||||
extra.push_str(&format!(
|
||||
" class {dep_id}[\"{}\"] {{\n <<module>>\n }}\n",
|
||||
dep_mod.as_str()
|
||||
));
|
||||
let label = if *count == 1 { "1 dep".to_string() } else { format!("{count} deps") };
|
||||
extra.push_str(&format!(" {src_id} --> {dep_id} : {label}\n"));
|
||||
}
|
||||
format!("{base}\n{extra}")
|
||||
};
|
||||
let file = RenderedFile::new("diagram.mmd", &content)?;
|
||||
Ok(RenderOutput::single(file))
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user