Skip to content

Commit 3a073f1

Browse files
calebcartwrighttopecongiro
authored andcommitted
fix: handling of newline_style conflicts (rust-lang#3850)
1 parent 5327c36 commit 3a073f1

File tree

3 files changed

+64
-11
lines changed

3 files changed

+64
-11
lines changed

src/emitter/diff.rs

+28
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,13 @@ impl Emitter for DiffEmitter {
3636
&self.config,
3737
);
3838
}
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+
let file_path = ensure_real_path(filename);
44+
writeln!(output, "Incorrect newline style in {}", file_path.display())?;
45+
return Ok(EmitterResult { has_diff: true });
3946
}
4047

4148
return Ok(EmitterResult { has_diff });
@@ -107,4 +114,25 @@ mod tests {
107114
format!("{}\n{}\n", bin_file, lib_file),
108115
)
109116
}
117+
118+
#[test]
119+
fn prints_newline_message_with_only_newline_style_diff() {
120+
let mut writer = Vec::new();
121+
let config = Config::default();
122+
let mut emitter = DiffEmitter::new(config);
123+
let _ = emitter
124+
.emit_formatted_file(
125+
&mut writer,
126+
FormattedFile {
127+
filename: &FileName::Real(PathBuf::from("src/lib.rs")),
128+
original_text: "fn empty() {}\n",
129+
formatted_text: "fn empty() {}\r\n",
130+
},
131+
)
132+
.unwrap();
133+
assert_eq!(
134+
String::from_utf8(writer).unwrap(),
135+
String::from("Incorrect newline style in src/lib.rs\n")
136+
);
137+
}
110138
}

src/formatting.rs

+8-2
Original file line numberDiff line numberDiff line change
@@ -243,8 +243,14 @@ impl<'b, T: Write + 'b> FormatHandler for Session<'b, T> {
243243
report: &mut FormatReport,
244244
) -> Result<(), ErrorKind> {
245245
if let Some(ref mut out) = self.out {
246-
match source_file::write_file(Some(source_map), &path, &result, out, &mut *self.emitter)
247-
{
246+
match source_file::write_file(
247+
Some(source_map),
248+
&path,
249+
&result,
250+
out,
251+
&mut *self.emitter,
252+
self.config.newline_style(),
253+
) {
248254
Ok(ref result) if result.has_diff => report.add_diff(),
249255
Err(e) => {
250256
// Create a new error with path_str to help users see which files failed

src/source_file.rs

+28-9
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use syntax::source_map::SourceMap;
66

77
use crate::config::FileName;
88
use crate::emitter::{self, Emitter};
9+
use crate::NewlineStyle;
910

1011
#[cfg(test)]
1112
use crate::config::Config;
@@ -32,7 +33,14 @@ where
3233

3334
emitter.emit_header(out)?;
3435
for &(ref filename, ref text) in source_file {
35-
write_file(None, filename, text, out, &mut *emitter)?;
36+
write_file(
37+
None,
38+
filename,
39+
text,
40+
out,
41+
&mut *emitter,
42+
config.newline_style(),
43+
)?;
3644
}
3745
emitter.emit_footer(out)?;
3846

@@ -45,6 +53,7 @@ pub(crate) fn write_file<T>(
4553
formatted_text: &str,
4654
out: &mut T,
4755
emitter: &mut dyn Emitter,
56+
newline_style: NewlineStyle,
4857
) -> Result<emitter::EmitterResult, io::Error>
4958
where
5059
T: Write,
@@ -65,15 +74,25 @@ where
6574
}
6675
}
6776

68-
// If parse session is around (cfg(not(test))) then try getting source from
69-
// there instead of hitting the file system. This also supports getting
77+
// SourceFile's in the SourceMap will always have Unix-style line endings
78+
// See: https://github.com/rust-lang/rustfmt/issues/3850
79+
// So if the user has explicitly overridden the rustfmt `newline_style`
80+
// config and `filename` is FileName::Real, then we must check the file system
81+
// to get the original file value in order to detect newline_style conflicts.
82+
// Otherwise, parse session is around (cfg(not(test))) and newline_style has been
83+
// left as the default value, then try getting source from the parse session
84+
// source map instead of hitting the file system. This also supports getting
7085
// original text for `FileName::Stdin`.
71-
let original_text = source_map
72-
.and_then(|x| x.get_source_file(&filename.into()))
73-
.and_then(|x| x.src.as_ref().map(ToString::to_string));
74-
let original_text = match original_text {
75-
Some(ori) => ori,
76-
None => fs::read_to_string(ensure_real_path(filename))?,
86+
let original_text = if newline_style != NewlineStyle::Auto && *filename != FileName::Stdin {
87+
fs::read_to_string(ensure_real_path(filename))?
88+
} else {
89+
match source_map
90+
.and_then(|x| x.get_source_file(&filename.into()))
91+
.and_then(|x| x.src.as_ref().map(ToString::to_string))
92+
{
93+
Some(ori) => ori,
94+
None => fs::read_to_string(ensure_real_path(filename))?,
95+
}
7796
};
7897

7998
let formatted_file = emitter::FormattedFile {

0 commit comments

Comments
 (0)