]> git.lizzy.rs Git - rust.git/blob - src/tools/rustfmt/src/emitter/diff.rs
Merge commit 'd7b5cbf065b88830ca519adcb73fad4c0d24b1c7' into clippyup
[rust.git] / src / tools / rustfmt / src / emitter / diff.rs
1 use super::*;
2 use crate::config::Config;
3 use crate::rustfmt_diff::{make_diff, print_diff};
4
5 pub(crate) struct DiffEmitter {
6     config: Config,
7 }
8
9 impl DiffEmitter {
10     pub(crate) fn new(config: Config) -> Self {
11         Self { config }
12     }
13 }
14
15 impl Emitter for DiffEmitter {
16     fn emit_formatted_file(
17         &mut self,
18         output: &mut dyn Write,
19         FormattedFile {
20             filename,
21             original_text,
22             formatted_text,
23         }: FormattedFile<'_>,
24     ) -> Result<EmitterResult, io::Error> {
25         const CONTEXT_SIZE: usize = 3;
26         let mismatch = make_diff(original_text, formatted_text, CONTEXT_SIZE);
27         let has_diff = !mismatch.is_empty();
28
29         if has_diff {
30             if self.config.print_misformatted_file_names() {
31                 writeln!(output, "{}", filename)?;
32             } else {
33                 print_diff(
34                     mismatch,
35                     |line_num| format!("Diff in {} at line {}:", filename, line_num),
36                     &self.config,
37                 );
38             }
39         } else if original_text != formatted_text {
40             // This occurs when the only difference between the original and formatted values
41             // is the newline style. This happens because The make_diff function compares the
42             // original and formatted values line by line, independent of line endings.
43             writeln!(output, "Incorrect newline style in {}", filename)?;
44             return Ok(EmitterResult { has_diff: true });
45         }
46
47         Ok(EmitterResult { has_diff })
48     }
49 }
50
51 #[cfg(test)]
52 mod tests {
53     use super::*;
54     use crate::config::Config;
55     use crate::FileName;
56     use std::path::PathBuf;
57
58     #[test]
59     fn does_not_print_when_no_files_reformatted() {
60         let mut writer = Vec::new();
61         let config = Config::default();
62         let mut emitter = DiffEmitter::new(config);
63         let result = emitter
64             .emit_formatted_file(
65                 &mut writer,
66                 FormattedFile {
67                     filename: &FileName::Real(PathBuf::from("src/lib.rs")),
68                     original_text: "fn empty() {}\n",
69                     formatted_text: "fn empty() {}\n",
70                 },
71             )
72             .unwrap();
73         assert_eq!(result.has_diff, false);
74         assert_eq!(writer.len(), 0);
75     }
76
77     #[test]
78     fn prints_file_names_when_config_is_enabled() {
79         let bin_file = "src/bin.rs";
80         let bin_original = "fn main() {\nprintln!(\"Hello, world!\");\n}";
81         let bin_formatted = "fn main() {\n    println!(\"Hello, world!\");\n}";
82         let lib_file = "src/lib.rs";
83         let lib_original = "fn greet() {\nprintln!(\"Greetings!\");\n}";
84         let lib_formatted = "fn greet() {\n    println!(\"Greetings!\");\n}";
85
86         let mut writer = Vec::new();
87         let mut config = Config::default();
88         config.set().print_misformatted_file_names(true);
89         let mut emitter = DiffEmitter::new(config);
90         let _ = emitter
91             .emit_formatted_file(
92                 &mut writer,
93                 FormattedFile {
94                     filename: &FileName::Real(PathBuf::from(bin_file)),
95                     original_text: bin_original,
96                     formatted_text: bin_formatted,
97                 },
98             )
99             .unwrap();
100         let _ = emitter
101             .emit_formatted_file(
102                 &mut writer,
103                 FormattedFile {
104                     filename: &FileName::Real(PathBuf::from(lib_file)),
105                     original_text: lib_original,
106                     formatted_text: lib_formatted,
107                 },
108             )
109             .unwrap();
110
111         assert_eq!(
112             String::from_utf8(writer).unwrap(),
113             format!("{}\n{}\n", bin_file, lib_file),
114         )
115     }
116
117     #[test]
118     fn prints_newline_message_with_only_newline_style_diff() {
119         let mut writer = Vec::new();
120         let config = Config::default();
121         let mut emitter = DiffEmitter::new(config);
122         let _ = emitter
123             .emit_formatted_file(
124                 &mut writer,
125                 FormattedFile {
126                     filename: &FileName::Real(PathBuf::from("src/lib.rs")),
127                     original_text: "fn empty() {}\n",
128                     formatted_text: "fn empty() {}\r\n",
129                 },
130             )
131             .unwrap();
132         assert_eq!(
133             String::from_utf8(writer).unwrap(),
134             String::from("Incorrect newline style in src/lib.rs\n")
135         );
136     }
137 }