1
- use crate :: NewlineStyle ;
1
+ use crate :: { FileName , NewlineStyle } ;
2
+ use std:: borrow:: Cow ;
3
+ use std:: fs;
2
4
3
5
/// Apply this newline style to the formatted text. When the style is set
4
6
/// to `Auto`, the `raw_input_text` is used to detect the existing line
@@ -8,10 +10,11 @@ use crate::NewlineStyle;
8
10
/// newlines, the `Native` style will be used.
9
11
pub ( crate ) fn apply_newline_style (
10
12
newline_style : NewlineStyle ,
13
+ path : & FileName ,
11
14
formatted_text : & mut String ,
12
15
raw_input_text : & str ,
13
16
) {
14
- * formatted_text = match effective_newline_style ( newline_style, raw_input_text) {
17
+ * formatted_text = match effective_newline_style ( newline_style, path , raw_input_text) {
15
18
EffectiveNewlineStyle :: Windows => convert_to_windows_newlines ( formatted_text) ,
16
19
EffectiveNewlineStyle :: Unix => convert_to_unix_newlines ( formatted_text) ,
17
20
}
@@ -25,10 +28,19 @@ enum EffectiveNewlineStyle {
25
28
26
29
fn effective_newline_style (
27
30
newline_style : NewlineStyle ,
31
+ path : & FileName ,
28
32
raw_input_text : & str ,
29
33
) -> EffectiveNewlineStyle {
30
34
match newline_style {
31
- NewlineStyle :: Auto => auto_detect_newline_style ( raw_input_text) ,
35
+ NewlineStyle :: Auto => match path. as_path ( ) {
36
+ Some ( path) => auto_detect_newline_style (
37
+ & fs:: read_to_string ( path)
38
+ . map ( |s| Cow :: Owned ( s) )
39
+ . unwrap_or_else ( |_| Cow :: Borrowed ( raw_input_text) ) ,
40
+ ) ,
41
+ None => auto_detect_newline_style ( raw_input_text) ,
42
+ } ,
43
+
32
44
NewlineStyle :: Native => native_newline_style ( ) ,
33
45
NewlineStyle :: Windows => EffectiveNewlineStyle :: Windows ,
34
46
NewlineStyle :: Unix => EffectiveNewlineStyle :: Unix ,
@@ -84,6 +96,8 @@ fn convert_to_unix_newlines(formatted_text: &str) -> String {
84
96
#[ cfg( test) ]
85
97
mod tests {
86
98
use super :: * ;
99
+ use std:: fs;
100
+ use tempdir:: TempDir ;
87
101
88
102
#[ test]
89
103
fn auto_detects_unix_newlines ( ) {
@@ -128,7 +142,28 @@ mod tests {
128
142
let raw_input_text = "One\n Two\n Three" ;
129
143
130
144
let mut out = String :: from ( formatted_text) ;
131
- apply_newline_style ( NewlineStyle :: Auto , & mut out, raw_input_text) ;
145
+ apply_newline_style (
146
+ NewlineStyle :: Auto ,
147
+ & FileName :: Stdin ,
148
+ & mut out,
149
+ raw_input_text,
150
+ ) ;
151
+ assert_eq ! ( "One\n Two\n Three" , & out, "auto should detect 'lf'" ) ;
152
+ }
153
+
154
+ #[ test]
155
+ fn auto_detects_and_applies_unix_newlines_from_real_file ( ) {
156
+ let formatted_text = "One\n Two\n Three" ;
157
+ let raw_input_text = "One\n Two\n Three" ;
158
+
159
+ let tmpdir = TempDir :: new ( "unix_newlines_from_real_file" ) . unwrap ( ) ;
160
+ let path = tmpdir. path ( ) . join ( "test.rs" ) ;
161
+ fs:: write ( & path, raw_input_text) . unwrap ( ) ;
162
+
163
+ let path = FileName :: Real ( path) ;
164
+
165
+ let mut out = String :: from ( formatted_text) ;
166
+ apply_newline_style ( NewlineStyle :: Auto , & path, & mut out, raw_input_text) ;
132
167
assert_eq ! ( "One\n Two\n Three" , & out, "auto should detect 'lf'" ) ;
133
168
}
134
169
@@ -138,17 +173,81 @@ mod tests {
138
173
let raw_input_text = "One\r \n Two\r \n Three" ;
139
174
140
175
let mut out = String :: from ( formatted_text) ;
141
- apply_newline_style ( NewlineStyle :: Auto , & mut out, raw_input_text) ;
176
+ apply_newline_style (
177
+ NewlineStyle :: Auto ,
178
+ & FileName :: Stdin ,
179
+ & mut out,
180
+ raw_input_text,
181
+ ) ;
142
182
assert_eq ! ( "One\r \n Two\r \n Three" , & out, "auto should detect 'crlf'" ) ;
143
183
}
144
184
185
+ #[ test]
186
+ fn auto_detects_and_applies_windows_newlines_from_real_file ( ) {
187
+ let formatted_text = "One\n Two\n Three" ;
188
+ let raw_input_text = "One\r \n Two\r \n Three" ;
189
+
190
+ let tmpdir = TempDir :: new ( "windows_newlines_from_real_file" ) . unwrap ( ) ;
191
+ let path = tmpdir. path ( ) . join ( "test.rs" ) ;
192
+ fs:: write ( & path, raw_input_text) . unwrap ( ) ;
193
+
194
+ let path = FileName :: Real ( path) ;
195
+
196
+ let mut out = String :: from ( formatted_text) ;
197
+ apply_newline_style ( NewlineStyle :: Auto , & path, & mut out, raw_input_text) ;
198
+ assert_eq ! ( "One\r \n Two\r \n Three" , & out, "auto should detect 'crlf'" ) ;
199
+ }
200
+
201
+ #[ test]
202
+ fn auto_detect_and_applies_windows_newlines_if_windows_newlines_read_from_file ( ) {
203
+ // Even if the `raw_input_text` does not contain crlf chars, we should still apply
204
+ // Them if we can read crlf from the input `FileName::Real(path)`.
205
+ // see issue https://github.com/rust-lang/rustfmt/issues/4097
206
+ let text = "One\n Two\n Three" ;
207
+
208
+ let tmpdir = TempDir :: new ( "windows_newlines_if_windows_newlines_read_from_file" ) . unwrap ( ) ;
209
+ let path = tmpdir. path ( ) . join ( "test.rs" ) ;
210
+ fs:: write ( & path, "One\r \n Two\r \n Three" ) . unwrap ( ) ;
211
+
212
+ let path = FileName :: Real ( path) ;
213
+
214
+ let mut out = String :: from ( text) ;
215
+ // Note that the source file contains `crlf`, while the `raw_input_text` contains `lf`
216
+ apply_newline_style ( NewlineStyle :: Auto , & path, & mut out, text) ;
217
+ assert_eq ! ( "One\r \n Two\r \n Three" , & out, "auto should detect 'crlf'" ) ;
218
+ }
219
+
220
+ #[ test]
221
+ fn auto_detect_and_applies_unix_newlines_if_unix_newlines_read_from_file ( ) {
222
+ // This following test is unlikely to happen in practice, but it is meant to illustrate
223
+ // that line endings found in the source files take precedence over the `raw_input_text`
224
+ // passed to apply_newline_style.
225
+ let text = "One\r \n Two\r \n Three" ;
226
+
227
+ let tmpdir = TempDir :: new ( "unix_newlines_if_unix_newlines_read_from_file" ) . unwrap ( ) ;
228
+ let path = tmpdir. path ( ) . join ( "test.rs" ) ;
229
+ fs:: write ( & path, "One\n Two\n Three" ) . unwrap ( ) ;
230
+
231
+ let path = FileName :: Real ( path) ;
232
+
233
+ let mut out = String :: from ( text) ;
234
+ // Note that the source file contains `lf`, while the `raw_input_text` contains `crlf`
235
+ apply_newline_style ( NewlineStyle :: Auto , & path, & mut out, text) ;
236
+ assert_eq ! ( "One\n Two\n Three" , & out, "auto should detect 'crlf'" ) ;
237
+ }
238
+
145
239
#[ test]
146
240
fn auto_detects_and_applies_native_newlines ( ) {
147
241
let formatted_text = "One\n Two\n Three" ;
148
242
let raw_input_text = "One Two Three" ;
149
243
150
244
let mut out = String :: from ( formatted_text) ;
151
- apply_newline_style ( NewlineStyle :: Auto , & mut out, raw_input_text) ;
245
+ apply_newline_style (
246
+ NewlineStyle :: Auto ,
247
+ & FileName :: Stdin ,
248
+ & mut out,
249
+ raw_input_text,
250
+ ) ;
152
251
153
252
if cfg ! ( windows) {
154
253
assert_eq ! (
@@ -244,7 +343,7 @@ mod tests {
244
343
newline_style : NewlineStyle ,
245
344
) {
246
345
let mut out = String :: from ( input) ;
247
- apply_newline_style ( newline_style, & mut out, input) ;
346
+ apply_newline_style ( newline_style, & FileName :: Stdin , & mut out, input) ;
248
347
assert_eq ! ( expected, & out) ;
249
348
}
250
349
}
0 commit comments