codelens_core/output/
json.rs1use std::io::Write;
4
5use crate::analyzer::stats::AnalysisResult;
6use crate::error::Result;
7
8use super::format::{OutputFormat, OutputOptions};
9
10pub struct JsonOutput {
12 pretty: bool,
13}
14
15impl JsonOutput {
16 pub fn new(pretty: bool) -> Self {
18 Self { pretty }
19 }
20}
21
22impl OutputFormat for JsonOutput {
23 fn name(&self) -> &'static str {
24 "json"
25 }
26
27 fn extension(&self) -> &'static str {
28 "json"
29 }
30
31 fn write(
32 &self,
33 result: &AnalysisResult,
34 _options: &OutputOptions,
35 writer: &mut dyn Write,
36 ) -> Result<()> {
37 if self.pretty {
38 serde_json::to_writer_pretty(&mut *writer, result)?;
39 } else {
40 serde_json::to_writer(&mut *writer, result)?;
41 }
42 writeln!(writer)?;
43 Ok(())
44 }
45}
46
47#[cfg(test)]
48mod tests {
49 use super::*;
50 use crate::analyzer::stats::{FileStats, LineStats, Summary};
51 use std::path::PathBuf;
52 use std::time::Duration;
53
54 fn make_test_result() -> AnalysisResult {
55 AnalysisResult {
56 files: vec![FileStats {
57 path: PathBuf::from("test.rs"),
58 language: "Rust".to_string(),
59 lines: LineStats {
60 total: 100,
61 code: 80,
62 comment: 10,
63 blank: 10,
64 },
65 size: 2000,
66 complexity: Default::default(),
67 }],
68 summary: Summary::from_file_stats(&[FileStats {
69 path: PathBuf::from("test.rs"),
70 language: "Rust".to_string(),
71 lines: LineStats {
72 total: 100,
73 code: 80,
74 comment: 10,
75 blank: 10,
76 },
77 size: 2000,
78 complexity: Default::default(),
79 }]),
80 elapsed: Duration::from_millis(100),
81 scanned_files: 1,
82 skipped_files: 0,
83 }
84 }
85
86 #[test]
87 fn test_json_output_name() {
88 let output = JsonOutput::new(false);
89 assert_eq!(output.name(), "json");
90 assert_eq!(output.extension(), "json");
91 }
92
93 #[test]
94 fn test_json_output_compact() {
95 let output = JsonOutput::new(false);
96 let result = make_test_result();
97 let options = OutputOptions::default();
98
99 let mut buffer = Vec::new();
100 output.write(&result, &options, &mut buffer).unwrap();
101
102 let json_str = String::from_utf8(buffer).unwrap();
103 assert!(json_str.contains("\"scanned_files\":1"));
104 assert!(json_str.contains("\"language\":\"Rust\""));
105 assert!(!json_str.contains(" \""));
107 }
108
109 #[test]
110 fn test_json_output_pretty() {
111 let output = JsonOutput::new(true);
112 let result = make_test_result();
113 let options = OutputOptions::default();
114
115 let mut buffer = Vec::new();
116 output.write(&result, &options, &mut buffer).unwrap();
117
118 let json_str = String::from_utf8(buffer).unwrap();
119 assert!(json_str.contains(" "));
121 }
122
123 #[test]
124 fn test_json_output_valid_json() {
125 let output = JsonOutput::new(false);
126 let result = make_test_result();
127 let options = OutputOptions::default();
128
129 let mut buffer = Vec::new();
130 output.write(&result, &options, &mut buffer).unwrap();
131
132 let json_str = String::from_utf8(buffer).unwrap();
133 let parsed: serde_json::Value = serde_json::from_str(&json_str).unwrap();
135 assert!(parsed.is_object());
136 }
137}