diff options
Diffstat (limited to '')
-rw-r--r-- | src/tools/rustfmt/src/emitter/diff.rs | 137 |
1 files changed, 137 insertions, 0 deletions
diff --git a/src/tools/rustfmt/src/emitter/diff.rs b/src/tools/rustfmt/src/emitter/diff.rs new file mode 100644 index 000000000..5e1f13446 --- /dev/null +++ b/src/tools/rustfmt/src/emitter/diff.rs @@ -0,0 +1,137 @@ +use super::*; +use crate::config::Config; +use crate::rustfmt_diff::{make_diff, print_diff}; + +pub(crate) struct DiffEmitter { + config: Config, +} + +impl DiffEmitter { + pub(crate) fn new(config: Config) -> Self { + Self { config } + } +} + +impl Emitter for DiffEmitter { + fn emit_formatted_file( + &mut self, + output: &mut dyn Write, + FormattedFile { + filename, + original_text, + formatted_text, + }: FormattedFile<'_>, + ) -> Result<EmitterResult, io::Error> { + const CONTEXT_SIZE: usize = 3; + let mismatch = make_diff(original_text, formatted_text, CONTEXT_SIZE); + let has_diff = !mismatch.is_empty(); + + if has_diff { + if self.config.print_misformatted_file_names() { + writeln!(output, "{}", filename)?; + } else { + print_diff( + mismatch, + |line_num| format!("Diff in {} at line {}:", filename, line_num), + &self.config, + ); + } + } else if original_text != formatted_text { + // This occurs when the only difference between the original and formatted values + // is the newline style. This happens because The make_diff function compares the + // original and formatted values line by line, independent of line endings. + writeln!(output, "Incorrect newline style in {}", filename)?; + return Ok(EmitterResult { has_diff: true }); + } + + Ok(EmitterResult { has_diff }) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::config::Config; + use crate::FileName; + use std::path::PathBuf; + + #[test] + fn does_not_print_when_no_files_reformatted() { + let mut writer = Vec::new(); + let config = Config::default(); + let mut emitter = DiffEmitter::new(config); + let result = emitter + .emit_formatted_file( + &mut writer, + FormattedFile { + filename: &FileName::Real(PathBuf::from("src/lib.rs")), + original_text: "fn empty() {}\n", + formatted_text: "fn empty() {}\n", + }, + ) + .unwrap(); + assert_eq!(result.has_diff, false); + assert_eq!(writer.len(), 0); + } + + #[test] + fn prints_file_names_when_config_is_enabled() { + let bin_file = "src/bin.rs"; + let bin_original = "fn main() {\nprintln!(\"Hello, world!\");\n}"; + let bin_formatted = "fn main() {\n println!(\"Hello, world!\");\n}"; + let lib_file = "src/lib.rs"; + let lib_original = "fn greet() {\nprintln!(\"Greetings!\");\n}"; + let lib_formatted = "fn greet() {\n println!(\"Greetings!\");\n}"; + + let mut writer = Vec::new(); + let mut config = Config::default(); + config.set().print_misformatted_file_names(true); + let mut emitter = DiffEmitter::new(config); + let _ = emitter + .emit_formatted_file( + &mut writer, + FormattedFile { + filename: &FileName::Real(PathBuf::from(bin_file)), + original_text: bin_original, + formatted_text: bin_formatted, + }, + ) + .unwrap(); + let _ = emitter + .emit_formatted_file( + &mut writer, + FormattedFile { + filename: &FileName::Real(PathBuf::from(lib_file)), + original_text: lib_original, + formatted_text: lib_formatted, + }, + ) + .unwrap(); + + assert_eq!( + String::from_utf8(writer).unwrap(), + format!("{}\n{}\n", bin_file, lib_file), + ) + } + + #[test] + fn prints_newline_message_with_only_newline_style_diff() { + let mut writer = Vec::new(); + let config = Config::default(); + let mut emitter = DiffEmitter::new(config); + let _ = emitter + .emit_formatted_file( + &mut writer, + FormattedFile { + filename: &FileName::Real(PathBuf::from("src/lib.rs")), + original_text: "fn empty() {}\n", + formatted_text: "fn empty() {}\r\n", + }, + ) + .unwrap(); + assert_eq!( + String::from_utf8(writer).unwrap(), + String::from("Incorrect newline style in src/lib.rs\n") + ); + } +} |