1use super::LintResult;
4use serde::{Deserialize, Serialize};
5
6#[derive(Serialize, Deserialize, Clone)]
7struct RdfJson {
8 source: RdfSource,
9 severity: String,
10 diagnostics: String,
11}
12
13#[derive(Serialize, Deserialize, Clone)]
14struct RdfSource {
15 name: String,
16 url: String,
17}
18
19#[derive(Serialize, Deserialize, Clone)]
20struct RdfDiagnostic {
21 message: String,
22 severity: String,
23 code: RdfCode,
24 location: RdfLocation,
25 suggestions: Vec<RdfSuggetion>,
26}
27
28#[derive(Serialize, Deserialize, Clone)]
29struct RdfLocation {
30 path: String,
31 range: RdfRange,
32}
33
34#[derive(Serialize, Deserialize, Clone)]
35struct RdfRange {
36 start: Option<RdfLineColumn>,
37 end: Option<RdfLineColumn>,
38}
39
40#[derive(Serialize, Deserialize, Clone)]
41struct RdfLineColumn {
42 line: usize,
44 column: usize,
47}
48
49#[derive(Serialize, Deserialize, Clone)]
50struct RdfSuggetion {
51 text: String,
52 range: RdfRange,
53}
54
55#[derive(Serialize, Deserialize, Clone)]
56struct RdfCode {
57 value: Option<String>,
58 url: String,
59}
60
61fn to_severity_str(severity: super::Severity) -> String {
62 match severity {
63 super::Severity::Error => "ERROR".to_owned(),
64 super::Severity::Warning => "WARNING".to_owned(),
65 super::Severity::Pass => "PASS".to_owned(),
66 }
67}
68
69#[doc(hidden)]
72pub(crate) fn to_rdjson_diagnostics(lint_result: &LintResult) -> Vec<String> {
73 let mut diagnostics = vec![];
74 lint_result.lines.iter().for_each(|line_result| {
75 let start: RdfLineColumn = RdfLineColumn {
76 line: line_result.line,
77 column: line_result.col,
78 };
79 let end = RdfLineColumn {
80 line: line_result.line + line_result.old.split("\n").count() - 1,
81 column: line_result.col + line_result.old.split("\n").last().unwrap_or("").len(),
82 };
83
84 let rdf_diagnostic: RdfDiagnostic = RdfDiagnostic {
85 message: "".to_owned(),
86 location: RdfLocation {
87 path: lint_result.filepath.replace("./", ""),
88 range: RdfRange {
89 start: Some(start.clone()),
90 end: Some(end.clone()),
91 },
92 },
93 severity: to_severity_str(line_result.severity),
94 code: RdfCode {
95 value: Some("AutoCorrect".to_owned()),
96 url: "https://github.com/huacnlee/autocorrect".to_owned(),
97 },
98 suggestions: vec![RdfSuggetion {
99 text: line_result.new.clone(),
100 range: RdfRange {
101 start: Some(start),
102 end: Some(end),
103 },
104 }],
105 };
106
107 diagnostics.push(serde_json::to_string(&rdf_diagnostic).unwrap())
108 });
109
110 diagnostics
111}
112
113#[doc(hidden)]
114pub fn to_lint_results_rdjson(lint_results: Vec<LintResult>) -> String {
115 let diagnostics = lint_results
116 .iter()
117 .flat_map(to_rdjson_diagnostics)
118 .collect::<Vec<_>>()
119 .join(",");
120 format!(
121 r#"{{"source":{{"name":"AutoCorrect Lint","url": "https://github.com/huacnlee/autocorrect"}},"diagnostics": [{diagnostics}]}}"#,
122 )
123}
124
125#[cfg(test)]
126mod tests {
127 #[test]
128 fn test_to_lint_results_rdjson() {
129 let rdjson = super::to_lint_results_rdjson(crate::result::json::crate_test_lint_results());
130
131 let expected = r#"{"source":{"name":"AutoCorrect Lint","url": "https://github.com/huacnlee/autocorrect"},"diagnostics": [{"message":"","severity":"ERROR","code":{"value":"AutoCorrect","url":"https://github.com/huacnlee/autocorrect"},"location":{"path":"test/foo/bar.rs","range":{"start":{"line":1,"column":1},"end":{"line":1,"column":13}}},"suggestions":[{"text":"hello 你好。","range":{"start":{"line":1,"column":1},"end":{"line":1,"column":13}}}]},{"message":"","severity":"ERROR","code":{"value":"AutoCorrect","url":"https://github.com/huacnlee/autocorrect"},"location":{"path":"test/foo/bar.rs","range":{"start":{"line":2,"column":1},"end":{"line":2,"column":14}}},"suggestions":[{"text":"这是第 2 行","range":{"start":{"line":2,"column":1},"end":{"line":2,"column":14}}}]}]}"#;
132 if expected != rdjson {
133 println!("--------------- rdjson:\n{}", rdjson);
134 }
135 assert_json_eq!(expected, rdjson);
136 }
137}