mirror of
https://github.com/rust-lang/rust.git
synced 2025-01-22 12:43:36 +00:00
Merge pull request #3526 from bash/refactor-apply-newline-style
Refactor apply newline style
This commit is contained in:
commit
4bc5911348
@ -22,62 +22,6 @@ pub enum NewlineStyle {
|
||||
Native,
|
||||
}
|
||||
|
||||
impl NewlineStyle {
|
||||
fn auto_detect(raw_input_text: &str) -> NewlineStyle {
|
||||
if let Some(pos) = raw_input_text.find('\n') {
|
||||
let pos = pos.saturating_sub(1);
|
||||
if let Some('\r') = raw_input_text.chars().nth(pos) {
|
||||
NewlineStyle::Windows
|
||||
} else {
|
||||
NewlineStyle::Unix
|
||||
}
|
||||
} else {
|
||||
NewlineStyle::Native
|
||||
}
|
||||
}
|
||||
|
||||
fn native() -> NewlineStyle {
|
||||
if cfg!(windows) {
|
||||
NewlineStyle::Windows
|
||||
} else {
|
||||
NewlineStyle::Unix
|
||||
}
|
||||
}
|
||||
|
||||
/// Apply this newline style to the formatted text. When the style is set
|
||||
/// to `Auto`, the `raw_input_text` is used to detect the existing line
|
||||
/// endings.
|
||||
///
|
||||
/// If the style is set to `Auto` and `raw_input_text` contains no
|
||||
/// newlines, the `Native` style will be used.
|
||||
pub(crate) fn apply(self, formatted_text: &mut String, raw_input_text: &str) {
|
||||
use crate::NewlineStyle::*;
|
||||
let mut style = self;
|
||||
if style == Auto {
|
||||
style = Self::auto_detect(raw_input_text);
|
||||
}
|
||||
if style == Native {
|
||||
style = Self::native();
|
||||
}
|
||||
match style {
|
||||
Windows => {
|
||||
let mut transformed = String::with_capacity(2 * formatted_text.capacity());
|
||||
for c in formatted_text.chars() {
|
||||
match c {
|
||||
'\n' => transformed.push_str("\r\n"),
|
||||
'\r' => continue,
|
||||
c => transformed.push(c),
|
||||
}
|
||||
}
|
||||
*formatted_text = transformed;
|
||||
}
|
||||
Unix => return,
|
||||
Native => unreachable!("NewlineStyle::Native"),
|
||||
Auto => unreachable!("NewlineStyle::Auto"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[config_type]
|
||||
/// Where to put the opening brace of items (`fn`, `impl`, etc.).
|
||||
pub enum BraceStyle {
|
||||
@ -412,59 +356,3 @@ impl Edition {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_newline_style_auto_detect() {
|
||||
let lf = "One\nTwo\nThree";
|
||||
let crlf = "One\r\nTwo\r\nThree";
|
||||
let none = "One Two Three";
|
||||
|
||||
assert_eq!(NewlineStyle::Unix, NewlineStyle::auto_detect(lf));
|
||||
assert_eq!(NewlineStyle::Windows, NewlineStyle::auto_detect(crlf));
|
||||
assert_eq!(NewlineStyle::Native, NewlineStyle::auto_detect(none));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_newline_style_auto_apply() {
|
||||
let auto = NewlineStyle::Auto;
|
||||
|
||||
let formatted_text = "One\nTwo\nThree";
|
||||
let raw_input_text = "One\nTwo\nThree";
|
||||
|
||||
let mut out = String::from(formatted_text);
|
||||
auto.apply(&mut out, raw_input_text);
|
||||
assert_eq!("One\nTwo\nThree", &out, "auto should detect 'lf'");
|
||||
|
||||
let formatted_text = "One\nTwo\nThree";
|
||||
let raw_input_text = "One\r\nTwo\r\nThree";
|
||||
|
||||
let mut out = String::from(formatted_text);
|
||||
auto.apply(&mut out, raw_input_text);
|
||||
assert_eq!("One\r\nTwo\r\nThree", &out, "auto should detect 'crlf'");
|
||||
|
||||
#[cfg(not(windows))]
|
||||
{
|
||||
let formatted_text = "One\nTwo\nThree";
|
||||
let raw_input_text = "One Two Three";
|
||||
|
||||
let mut out = String::from(formatted_text);
|
||||
auto.apply(&mut out, raw_input_text);
|
||||
assert_eq!(
|
||||
"One\nTwo\nThree", &out,
|
||||
"auto-native-unix should detect 'lf'"
|
||||
);
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
{
|
||||
let formatted_text = "One\nTwo\nThree";
|
||||
let raw_input_text = "One Two Three";
|
||||
|
||||
let mut out = String::from(formatted_text);
|
||||
auto.apply(&mut out, raw_input_text);
|
||||
assert_eq!(
|
||||
"One\r\nTwo\r\nThree", &out,
|
||||
"auto-native-windows should detect 'crlf'"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -12,6 +12,7 @@ use syntax::errors::{DiagnosticBuilder, Handler};
|
||||
use syntax::parse::{self, ParseSess};
|
||||
use syntax::source_map::{FilePathMapping, SourceMap, Span, DUMMY_SP};
|
||||
|
||||
use self::newline_style::apply_newline_style;
|
||||
use crate::comment::{CharClasses, FullCodeCharKind};
|
||||
use crate::config::{Config, FileName, Verbosity};
|
||||
use crate::ignore_path::IgnorePathSet;
|
||||
@ -20,6 +21,8 @@ use crate::utils::{count_newlines, get_skip_macro_names};
|
||||
use crate::visitor::{FmtVisitor, SnippetProvider};
|
||||
use crate::{modules, source_file, ErrorKind, FormatReport, Input, Session};
|
||||
|
||||
mod newline_style;
|
||||
|
||||
// A map of the files of a crate, with their new content
|
||||
pub(crate) type SourceFile = Vec<FileRecord>;
|
||||
pub(crate) type FileRecord = (FileName, String);
|
||||
@ -191,9 +194,12 @@ impl<'a, T: FormatHandler + 'a> FormatContext<'a, T> {
|
||||
&self.config,
|
||||
&self.report,
|
||||
);
|
||||
self.config
|
||||
.newline_style()
|
||||
.apply(&mut visitor.buffer, &big_snippet);
|
||||
|
||||
apply_newline_style(
|
||||
self.config.newline_style(),
|
||||
&mut visitor.buffer,
|
||||
&big_snippet,
|
||||
);
|
||||
|
||||
if visitor.macro_rewrite_failure {
|
||||
self.report.add_macro_format_failure();
|
||||
|
250
src/formatting/newline_style.rs
Normal file
250
src/formatting/newline_style.rs
Normal file
@ -0,0 +1,250 @@
|
||||
use crate::NewlineStyle;
|
||||
|
||||
/// Apply this newline style to the formatted text. When the style is set
|
||||
/// to `Auto`, the `raw_input_text` is used to detect the existing line
|
||||
/// endings.
|
||||
///
|
||||
/// If the style is set to `Auto` and `raw_input_text` contains no
|
||||
/// newlines, the `Native` style will be used.
|
||||
pub(crate) fn apply_newline_style(
|
||||
newline_style: NewlineStyle,
|
||||
formatted_text: &mut String,
|
||||
raw_input_text: &str,
|
||||
) {
|
||||
*formatted_text = match effective_newline_style(newline_style, raw_input_text) {
|
||||
EffectiveNewlineStyle::Windows => convert_to_windows_newlines(formatted_text),
|
||||
EffectiveNewlineStyle::Unix => convert_to_unix_newlines(formatted_text),
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
enum EffectiveNewlineStyle {
|
||||
Windows,
|
||||
Unix,
|
||||
}
|
||||
|
||||
fn effective_newline_style(
|
||||
newline_style: NewlineStyle,
|
||||
raw_input_text: &str,
|
||||
) -> EffectiveNewlineStyle {
|
||||
match newline_style {
|
||||
NewlineStyle::Auto => auto_detect_newline_style(raw_input_text),
|
||||
NewlineStyle::Native => native_newline_style(),
|
||||
NewlineStyle::Windows => EffectiveNewlineStyle::Windows,
|
||||
NewlineStyle::Unix => EffectiveNewlineStyle::Unix,
|
||||
}
|
||||
}
|
||||
|
||||
const LINE_FEED: char = '\n';
|
||||
const CARRIAGE_RETURN: char = '\r';
|
||||
const WINDOWS_NEWLINE: &str = "\r\n";
|
||||
const UNIX_NEWLINE: &str = "\n";
|
||||
|
||||
fn auto_detect_newline_style(raw_input_text: &str) -> EffectiveNewlineStyle {
|
||||
let first_line_feed_pos = raw_input_text.chars().position(|ch| ch == LINE_FEED);
|
||||
match first_line_feed_pos {
|
||||
Some(first_line_feed_pos) => {
|
||||
let char_before_line_feed_pos = first_line_feed_pos.saturating_sub(1);
|
||||
let char_before_line_feed = raw_input_text.chars().nth(char_before_line_feed_pos);
|
||||
match char_before_line_feed {
|
||||
Some(CARRIAGE_RETURN) => EffectiveNewlineStyle::Windows,
|
||||
_ => EffectiveNewlineStyle::Unix,
|
||||
}
|
||||
}
|
||||
None => native_newline_style(),
|
||||
}
|
||||
}
|
||||
|
||||
fn native_newline_style() -> EffectiveNewlineStyle {
|
||||
if cfg!(windows) {
|
||||
EffectiveNewlineStyle::Windows
|
||||
} else {
|
||||
EffectiveNewlineStyle::Unix
|
||||
}
|
||||
}
|
||||
|
||||
fn convert_to_windows_newlines(formatted_text: &String) -> String {
|
||||
let mut transformed = String::with_capacity(2 * formatted_text.capacity());
|
||||
let mut chars = formatted_text.chars().peekable();
|
||||
while let Some(current_char) = chars.next() {
|
||||
let next_char = chars.peek();
|
||||
match current_char {
|
||||
LINE_FEED => transformed.push_str(WINDOWS_NEWLINE),
|
||||
CARRIAGE_RETURN if next_char == Some(&LINE_FEED) => {}
|
||||
current_char => transformed.push(current_char),
|
||||
}
|
||||
}
|
||||
transformed
|
||||
}
|
||||
|
||||
fn convert_to_unix_newlines(formatted_text: &String) -> String {
|
||||
formatted_text.replace(WINDOWS_NEWLINE, UNIX_NEWLINE)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn auto_detects_unix_newlines() {
|
||||
assert_eq!(
|
||||
EffectiveNewlineStyle::Unix,
|
||||
auto_detect_newline_style("One\nTwo\nThree")
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn auto_detects_windows_newlines() {
|
||||
assert_eq!(
|
||||
EffectiveNewlineStyle::Windows,
|
||||
auto_detect_newline_style("One\r\nTwo\r\nThree")
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn auto_detects_windows_newlines_with_multibyte_char_on_first_line() {
|
||||
assert_eq!(
|
||||
EffectiveNewlineStyle::Windows,
|
||||
auto_detect_newline_style("A 🎢 of a first line\r\nTwo\r\nThree")
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn falls_back_to_native_newlines_if_no_newlines_are_found() {
|
||||
let expected_newline_style = if cfg!(windows) {
|
||||
EffectiveNewlineStyle::Windows
|
||||
} else {
|
||||
EffectiveNewlineStyle::Unix
|
||||
};
|
||||
assert_eq!(
|
||||
expected_newline_style,
|
||||
auto_detect_newline_style("One Two Three")
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn auto_detects_and_applies_unix_newlines() {
|
||||
let formatted_text = "One\nTwo\nThree";
|
||||
let raw_input_text = "One\nTwo\nThree";
|
||||
|
||||
let mut out = String::from(formatted_text);
|
||||
apply_newline_style(NewlineStyle::Auto, &mut out, raw_input_text);
|
||||
assert_eq!("One\nTwo\nThree", &out, "auto should detect 'lf'");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn auto_detects_and_applies_windows_newlines() {
|
||||
let formatted_text = "One\nTwo\nThree";
|
||||
let raw_input_text = "One\r\nTwo\r\nThree";
|
||||
|
||||
let mut out = String::from(formatted_text);
|
||||
apply_newline_style(NewlineStyle::Auto, &mut out, raw_input_text);
|
||||
assert_eq!("One\r\nTwo\r\nThree", &out, "auto should detect 'crlf'");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn auto_detects_and_applies_native_newlines() {
|
||||
let formatted_text = "One\nTwo\nThree";
|
||||
let raw_input_text = "One Two Three";
|
||||
|
||||
let mut out = String::from(formatted_text);
|
||||
apply_newline_style(NewlineStyle::Auto, &mut out, raw_input_text);
|
||||
|
||||
if cfg!(windows) {
|
||||
assert_eq!(
|
||||
"One\r\nTwo\r\nThree", &out,
|
||||
"auto-native-windows should detect 'crlf'"
|
||||
);
|
||||
} else {
|
||||
assert_eq!(
|
||||
"One\nTwo\nThree", &out,
|
||||
"auto-native-unix should detect 'lf'"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn applies_unix_newlines() {
|
||||
test_newlines_are_applied_correctly(
|
||||
"One\r\nTwo\nThree",
|
||||
"One\nTwo\nThree",
|
||||
NewlineStyle::Unix,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn applying_unix_newlines_changes_nothing_for_unix_newlines() {
|
||||
let formatted_text = "One\nTwo\nThree";
|
||||
test_newlines_are_applied_correctly(formatted_text, formatted_text, NewlineStyle::Unix);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn applies_unix_newlines_to_string_with_unix_and_windows_newlines() {
|
||||
test_newlines_are_applied_correctly(
|
||||
"One\r\nTwo\r\nThree\nFour",
|
||||
"One\nTwo\nThree\nFour",
|
||||
NewlineStyle::Unix,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn applies_windows_newlines_to_string_with_unix_and_windows_newlines() {
|
||||
test_newlines_are_applied_correctly(
|
||||
"One\nTwo\nThree\r\nFour",
|
||||
"One\r\nTwo\r\nThree\r\nFour",
|
||||
NewlineStyle::Windows,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn applying_windows_newlines_changes_nothing_for_windows_newlines() {
|
||||
let formatted_text = "One\r\nTwo\r\nThree";
|
||||
test_newlines_are_applied_correctly(formatted_text, formatted_text, NewlineStyle::Windows);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn keeps_carriage_returns_when_applying_windows_newlines_to_str_with_unix_newlines() {
|
||||
test_newlines_are_applied_correctly(
|
||||
"One\nTwo\nThree\rDrei",
|
||||
"One\r\nTwo\r\nThree\rDrei",
|
||||
NewlineStyle::Windows,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn keeps_carriage_returns_when_applying_unix_newlines_to_str_with_unix_newlines() {
|
||||
test_newlines_are_applied_correctly(
|
||||
"One\nTwo\nThree\rDrei",
|
||||
"One\nTwo\nThree\rDrei",
|
||||
NewlineStyle::Unix,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn keeps_carriage_returns_when_applying_windows_newlines_to_str_with_windows_newlines() {
|
||||
test_newlines_are_applied_correctly(
|
||||
"One\r\nTwo\r\nThree\rDrei",
|
||||
"One\r\nTwo\r\nThree\rDrei",
|
||||
NewlineStyle::Windows,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn keeps_carriage_returns_when_applying_unix_newlines_to_str_with_windows_newlines() {
|
||||
test_newlines_are_applied_correctly(
|
||||
"One\r\nTwo\r\nThree\rDrei",
|
||||
"One\nTwo\nThree\rDrei",
|
||||
NewlineStyle::Unix,
|
||||
);
|
||||
}
|
||||
|
||||
fn test_newlines_are_applied_correctly(
|
||||
input: &str,
|
||||
expected: &str,
|
||||
newline_style: NewlineStyle,
|
||||
) {
|
||||
let mut out = String::from(input);
|
||||
apply_newline_style(newline_style, &mut out, input);
|
||||
assert_eq!(expected, &out);
|
||||
}
|
||||
}
|
2
tests/source/preserves_carriage_return_for_unix.rs
Normal file
2
tests/source/preserves_carriage_return_for_unix.rs
Normal file
@ -0,0 +1,2 @@
|
||||
// rustfmt-newline_style: Unix
|
||||
// Foo
Bar
|
2
tests/source/preserves_carriage_return_for_windows.rs
Normal file
2
tests/source/preserves_carriage_return_for_windows.rs
Normal file
@ -0,0 +1,2 @@
|
||||
// rustfmt-newline_style: Windows
|
||||
// Foo
Bar
|
2
tests/target/preserves_carriage_return_for_unix.rs
Normal file
2
tests/target/preserves_carriage_return_for_unix.rs
Normal file
@ -0,0 +1,2 @@
|
||||
// rustfmt-newline_style: Unix
|
||||
// Foo
Bar
|
2
tests/target/preserves_carriage_return_for_windows.rs
Normal file
2
tests/target/preserves_carriage_return_for_windows.rs
Normal file
@ -0,0 +1,2 @@
|
||||
// rustfmt-newline_style: Windows
|
||||
// Foo
Bar
|
Loading…
Reference in New Issue
Block a user