mod chunk;
mod dry;
mod functions;
mod misc;
mod reporter;
mod srp_coupling;
use chunk::JsonChunk;
use reporter::JsonReporter;
use super::json_types::JsonOutput;
use super::AnalysisResult;
use crate::ports::Reporter;
use crate::report::Summary;
pub(crate) struct JsonOutputComposer<'a> {
pub summary: &'a Summary,
}
impl<'a> JsonOutputComposer<'a> {
pub(crate) fn compose(
&self,
merged: JsonChunk,
orphan_suppressions: Vec<crate::adapters::report::json_types::JsonOrphanSuppression>,
) -> String {
let output = JsonOutput {
summary: misc::build_summary(self.summary),
functions: merged.functions,
coupling: if merged.coupling_modules.is_empty() && merged.cycles.is_empty() {
None
} else {
Some(super::json_types::JsonCoupling {
modules: merged.coupling_modules,
cycles: merged.cycles,
sdp_violations: merged.sdp_violations,
})
},
duplicates: merged.duplicates,
dead_code: merged.dead_code,
fragments: merged.fragments,
wildcard_warnings: merged.wildcards,
boilerplate: merged.boilerplate,
tq_warnings: merged.tq_warnings,
structural_warnings: merged.structural,
repeated_matches: merged.repeated_matches,
srp: if merged.srp_struct.is_empty()
&& merged.srp_module.is_empty()
&& merged.srp_param.is_empty()
{
None
} else {
Some(super::json_types::JsonSrp {
struct_warnings: merged.srp_struct,
module_warnings: merged.srp_module,
param_warnings: merged.srp_param,
})
},
orphan_suppressions,
architecture_findings: merged.architecture,
};
serde_json::to_string_pretty(&output)
.unwrap_or_else(|e| format!("{{\"error\":\"JSON serialization failed: {e}\"}}"))
}
}
pub fn print_json(analysis: &AnalysisResult) {
let json = build_json_string(analysis);
println!("{json}");
}
pub(crate) fn build_json_string(analysis: &AnalysisResult) -> String {
let composer = JsonOutputComposer {
summary: &analysis.summary,
};
let reporter = JsonReporter {
findings: &analysis.findings,
composer: &composer,
};
reporter.render(&analysis.findings, &analysis.data)
}