nu_lint/output/
json.rs

1use serde::Serialize;
2
3use super::{Summary, calculate_line_column, read_source_code};
4use crate::{Fix, violation::Violation};
5
6pub fn format_json(violations: &[Violation]) -> String {
7    let json_violations: Vec<JsonViolation> = violations.iter().map(violation_to_json).collect();
8
9    let summary = Summary::from_violations(violations);
10    let output = JsonOutput {
11        violations: json_violations,
12        summary,
13    };
14
15    serde_json::to_string_pretty(&output).unwrap_or_default()
16}
17
18fn violation_to_json(violation: &Violation) -> JsonViolation {
19    let source_code = read_source_code(violation.file.as_ref());
20
21    let (line_start, column_start) = calculate_line_column(&source_code, violation.span.start);
22    let (line_end, column_end) = calculate_line_column(&source_code, violation.span.end);
23
24    JsonViolation {
25        rule_id: violation.rule_id.to_string(),
26        lint_level: violation.lint_level.to_string(),
27        message: violation.message.to_string(),
28        file: violation.file.as_ref().map(ToString::to_string),
29        line_start,
30        line_end,
31        column_start,
32        column_end,
33        offset_start: violation.span.start,
34        offset_end: violation.span.end,
35        suggestion: violation.help.as_ref().map(ToString::to_string),
36        fix: violation.fix.as_ref().map(fix_to_json),
37    }
38}
39
40fn fix_to_json(fix: &Fix) -> JsonFix {
41    JsonFix {
42        description: fix.explanation.to_string(),
43        replacements: fix
44            .replacements
45            .iter()
46            .map(|r| JsonReplacement {
47                offset_start: r.span.start,
48                offset_end: r.span.end,
49                new_text: r.replacement_text.to_string(),
50            })
51            .collect(),
52    }
53}
54
55#[derive(Serialize)]
56pub struct JsonOutput {
57    pub violations: Vec<JsonViolation>,
58    pub summary: Summary,
59}
60
61#[derive(Serialize)]
62pub struct JsonViolation {
63    pub rule_id: String,
64    pub lint_level: String,
65    pub message: String,
66    pub file: Option<String>,
67    pub line_start: usize,
68    pub line_end: usize,
69    pub column_start: usize,
70    pub column_end: usize,
71    pub offset_start: usize,
72    pub offset_end: usize,
73    pub suggestion: Option<String>,
74    pub fix: Option<JsonFix>,
75}
76
77#[derive(Serialize)]
78pub struct JsonFix {
79    pub description: String,
80    pub replacements: Vec<JsonReplacement>,
81}
82
83#[derive(Serialize)]
84pub struct JsonReplacement {
85    pub offset_start: usize,
86    pub offset_end: usize,
87    pub new_text: String,
88}