rustfmt_nightly/emitter/
diff.rs
1use super::*;
2use crate::config::Config;
3use crate::rustfmt_diff::{make_diff, print_diff};
4
5pub(crate) struct DiffEmitter {
6 config: Config,
7}
8
9impl DiffEmitter {
10 pub(crate) fn new(config: Config) -> Self {
11 Self { config }
12 }
13}
14
15impl 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 {}:{}:", filename, line_num),
36 &self.config,
37 );
38 }
39 } else if original_text != formatted_text {
40 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)]
52mod tests {
53 use super::*;
54 use std::path::PathBuf;
55
56 #[test]
57 fn does_not_print_when_no_files_reformatted() {
58 let mut writer = Vec::new();
59 let config = Config::default();
60 let mut emitter = DiffEmitter::new(config);
61 let result = emitter
62 .emit_formatted_file(
63 &mut writer,
64 FormattedFile {
65 filename: &FileName::Real(PathBuf::from("src/lib.rs")),
66 original_text: "fn empty() {}\n",
67 formatted_text: "fn empty() {}\n",
68 },
69 )
70 .unwrap();
71 assert_eq!(result.has_diff, false);
72 assert_eq!(writer.len(), 0);
73 }
74
75 #[test]
76 fn prints_file_names_when_config_is_enabled() {
77 let bin_file = "src/bin.rs";
78 let bin_original = "fn main() {\nprintln!(\"Hello, world!\");\n}";
79 let bin_formatted = "fn main() {\n println!(\"Hello, world!\");\n}";
80 let lib_file = "src/lib.rs";
81 let lib_original = "fn greet() {\nprintln!(\"Greetings!\");\n}";
82 let lib_formatted = "fn greet() {\n println!(\"Greetings!\");\n}";
83
84 let mut writer = Vec::new();
85 let mut config = Config::default();
86 config.set().print_misformatted_file_names(true);
87 let mut emitter = DiffEmitter::new(config);
88 let _ = emitter
89 .emit_formatted_file(
90 &mut writer,
91 FormattedFile {
92 filename: &FileName::Real(PathBuf::from(bin_file)),
93 original_text: bin_original,
94 formatted_text: bin_formatted,
95 },
96 )
97 .unwrap();
98 let _ = emitter
99 .emit_formatted_file(
100 &mut writer,
101 FormattedFile {
102 filename: &FileName::Real(PathBuf::from(lib_file)),
103 original_text: lib_original,
104 formatted_text: lib_formatted,
105 },
106 )
107 .unwrap();
108
109 assert_eq!(
110 String::from_utf8(writer).unwrap(),
111 format!("{bin_file}\n{lib_file}\n"),
112 )
113 }
114
115 #[test]
116 fn prints_newline_message_with_only_newline_style_diff() {
117 let mut writer = Vec::new();
118 let config = Config::default();
119 let mut emitter = DiffEmitter::new(config);
120 let _ = emitter
121 .emit_formatted_file(
122 &mut writer,
123 FormattedFile {
124 filename: &FileName::Real(PathBuf::from("src/lib.rs")),
125 original_text: "fn empty() {}\n",
126 formatted_text: "fn empty() {}\r\n",
127 },
128 )
129 .unwrap();
130 assert_eq!(
131 String::from_utf8(writer).unwrap(),
132 String::from("Incorrect newline style in src/lib.rs\n")
133 );
134 }
135}