zuit_report/lib.rs
1//! Output formatters for zuit analysis reports.
2//!
3//! This crate provides six output formats for a [`zuit_core::engine::Report`]:
4//!
5//! | Format | Function | Notes |
6//! |--------|----------|-------|
7//! | JSON | [`json::render_json`] | Pretty-printed, stable field order. Documented in `docs/json-schema.md`. |
8//! | Terminal | [`terminal::render_terminal`] | Grouped by dimension → severity. Optional ANSI colour and OSC-8 hyperlinks. |
9//! | Markdown | [`markdown::render_markdown`] | Scoreboard table + collapsible `<details>` blocks, PR-comment friendly. |
10//! | SARIF | [`sarif::render_sarif`] | Valid SARIF 2.1.0; single merged run strategy for v1. |
11//! | Checkstyle | [`checkstyle::render_checkstyle`] | Checkstyle v8 XML; consumed by `IntelliJ` and `SonarQube`. |
12//! | `JUnit` | [`junit::render_junit`] | `JUnit` XML (Surefire/Maven flavour); consumed by GitHub Actions, Jenkins, and GitLab CI. |
13//!
14//! The top-level entry point is [`render`], which dispatches to the appropriate
15//! sub-module based on a [`ReportFormat`] value.
16#![warn(missing_docs)]
17
18pub mod checkstyle;
19pub mod json;
20pub mod junit;
21pub mod markdown;
22pub mod sarif;
23pub mod terminal;
24
25use zuit_core::engine::Report;
26
27pub use checkstyle::render_checkstyle;
28pub use json::render_json;
29pub use junit::render_junit;
30pub use markdown::render_markdown;
31pub use sarif::render_sarif;
32pub use terminal::render_terminal;
33
34/// The output format to render a [`Report`] into.
35#[derive(Debug, Clone, Copy, PartialEq, Eq)]
36pub enum ReportFormat {
37 /// Pretty-printed JSON with stable field order.
38 Json,
39 /// Coloured terminal output grouped by dimension and severity.
40 Terminal,
41 /// Markdown suitable for GitHub PR comments.
42 Markdown,
43 /// SARIF 2.1.0 — single merged run, valid per the SARIF 2.1.0 schema.
44 Sarif,
45 /// Checkstyle v8 XML — consumed by `IntelliJ` (Checkstyle plugin) and `SonarQube`.
46 Checkstyle,
47 /// `JUnit` XML (Surefire/Maven flavour) — consumed by GitHub Actions, Jenkins, and GitLab CI.
48 Junit,
49}
50
51/// Options that control how a report is rendered.
52///
53/// The default is CI-friendly (no colour, no hyperlinks).
54#[derive(Debug, Clone, Default)]
55pub struct RenderOptions {
56 /// When `true`, ANSI colour escape codes are emitted in terminal output.
57 /// When `false`, output is plain ASCII.
58 pub use_color: bool,
59 /// When `true`, file paths in terminal output are wrapped in OSC-8 hyperlinks.
60 pub use_hyperlinks: bool,
61}
62
63/// Errors that can occur while rendering a report.
64#[derive(Debug, thiserror::Error)]
65pub enum ReportError {
66 /// The requested format is not implemented.
67 #[error("not implemented: {0}")]
68 NotImplemented(&'static str),
69 /// A `serde_json` serialization failure.
70 #[error("serialization error: {0}")]
71 Serialize(#[from] serde_json::Error),
72 /// A `std::fmt::Write` failure (should never occur in practice because
73 /// `String`'s `Write` impl is infallible, but the `?` operator requires it).
74 #[error(transparent)]
75 Fmt(#[from] std::fmt::Error),
76 /// A `quick_xml` write or encoding failure.
77 #[error("XML error: {0}")]
78 Xml(#[from] quick_xml::Error),
79}
80
81/// Renders `report` in the requested format.
82///
83/// For [`ReportFormat::Terminal`] the default [`RenderOptions`] are used
84/// (no colour, no hyperlinks). Call [`render_terminal`] directly for full control.
85///
86/// # Errors
87///
88/// Returns [`ReportError::Serialize`] if JSON serialization fails (JSON or SARIF).
89/// Returns [`ReportError::Fmt`] if string formatting fails (Markdown or terminal).
90pub fn render(
91 format: ReportFormat,
92 report: &Report,
93 opts: &RenderOptions,
94) -> Result<String, ReportError> {
95 match format {
96 ReportFormat::Json => render_json(report),
97 ReportFormat::Terminal => render_terminal(report, opts),
98 ReportFormat::Markdown => render_markdown(report),
99 ReportFormat::Sarif => render_sarif(report),
100 ReportFormat::Checkstyle => render_checkstyle(report),
101 ReportFormat::Junit => render_junit(report),
102 }
103}