1use std::collections::HashSet;
4use std::fmt::Write as _;
5
6use crate::{Diagnostic, Level, Lint};
7
8pub fn render(diagnostics: &[Diagnostic], summary: bool) -> String {
10 let mut out = String::new();
11 let mut explained: HashSet<Lint> = HashSet::new();
12 for d in diagnostics {
13 let gutter = d.line.to_string().len();
14 let pad = " ".repeat(gutter);
15 let _ = writeln!(out, "{}[ravenrs::{}]: {}", d.level.label(), d.lint.name(), d.message);
16 let _ = writeln!(out, "{pad}--> {}:{}:{}", d.file.display(), d.line, d.column);
17 let _ = writeln!(out, "{pad} |");
18 let _ = writeln!(out, "{} | {}", d.line, d.snippet);
19 let marks = "^".repeat(d.end_column.saturating_sub(d.column).max(1));
20 let _ = writeln!(out, "{pad} | {}{marks}", " ".repeat(d.column.saturating_sub(1)));
21 let _ = writeln!(out, "{pad} |");
22 let _ = writeln!(out, "{pad} = help: {}", d.help);
23 if explained.insert(d.lint) {
24 let _ = writeln!(
25 out,
26 "{pad} = note: `ravenrs::{}` ({}) is {}; fix the code rather than silencing it",
27 d.lint.name(),
28 d.lint.summary(),
29 match d.level {
30 Level::Deny => "denied",
31 _ => "a warning",
32 },
33 );
34 }
35 out.push('\n');
36 }
37 if summary && !diagnostics.is_empty() {
38 let errors = diagnostics.iter().filter(|d| d.level == Level::Deny).count();
39 let warnings = diagnostics.len() - errors;
40 let plural = |n: usize, word: &str| format!("{n} {word}{}", if n == 1 { "" } else { "s" });
41 let _ = writeln!(
42 out,
43 "error: ravenrs-lint found {} and {}. Fix each one as its help says, then run it again.",
44 plural(errors, "error"),
45 plural(warnings, "warning"),
46 );
47 }
48 out
49}
50
51pub fn render_json(diagnostics: &[Diagnostic]) -> String {
53 let mut out = String::new();
54 for d in diagnostics {
55 let value = serde_json::json!({
56 "lint": format!("ravenrs::{}", d.lint.name()),
57 "level": d.level.label(),
58 "file": d.file.display().to_string(),
59 "line": d.line,
60 "column": d.column,
61 "end_column": d.end_column,
62 "message": d.message,
63 "help": d.help,
64 });
65 out.push_str(&value.to_string());
66 out.push('\n');
67 }
68 out
69}