Skip to content

OBSOLETE - REPLACED - Correct newline-style in json emitter #5417

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
162 changes: 84 additions & 78 deletions Cargo.lock

Large diffs are not rendered by default.

10 changes: 10 additions & 0 deletions src/emitter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ pub(crate) use self::json::*;
pub(crate) use self::modified_lines::*;
pub(crate) use self::stdout::*;
use crate::FileName;
use crate::NewlineStyle;
use std::io::{self, Write};
use std::path::Path;

Expand Down Expand Up @@ -33,6 +34,15 @@ pub(crate) trait Emitter {
&mut self,
output: &mut dyn Write,
formatted_file: FormattedFile<'_>,
) -> Result<EmitterResult, io::Error> {
self.emit_formatted_file_with_line_style(output, formatted_file, NewlineStyle::Auto)
}

fn emit_formatted_file_with_line_style(
&mut self,
output: &mut dyn Write,
formatted_file: FormattedFile<'_>,
newline_style: NewlineStyle,
) -> Result<EmitterResult, io::Error>;

fn emit_header(&self, _output: &mut dyn Write) -> Result<(), io::Error> {
Expand Down
4 changes: 3 additions & 1 deletion src/emitter/checkstyle.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use self::xml::XmlEscaped;
use super::*;
use crate::rustfmt_diff::{make_diff, DiffLine, Mismatch};
use crate::NewlineStyle;
use std::io::{self, Write};

mod xml;
Expand All @@ -19,14 +20,15 @@ impl Emitter for CheckstyleEmitter {
writeln!(output, "</checkstyle>")
}

fn emit_formatted_file(
fn emit_formatted_file_with_line_style(
&mut self,
output: &mut dyn Write,
FormattedFile {
filename,
original_text,
formatted_text,
}: FormattedFile<'_>,
_: NewlineStyle,
) -> Result<EmitterResult, io::Error> {
const CONTEXT_SIZE: usize = 0;
let diff = make_diff(original_text, formatted_text, CONTEXT_SIZE);
Expand Down
4 changes: 3 additions & 1 deletion src/emitter/diff.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use super::*;
use crate::config::Config;
use crate::rustfmt_diff::{make_diff, print_diff};
use crate::NewlineStyle;

pub(crate) struct DiffEmitter {
config: Config,
Expand All @@ -13,14 +14,15 @@ impl DiffEmitter {
}

impl Emitter for DiffEmitter {
fn emit_formatted_file(
fn emit_formatted_file_with_line_style(
&mut self,
output: &mut dyn Write,
FormattedFile {
filename,
original_text,
formatted_text,
}: FormattedFile<'_>,
_: NewlineStyle,
) -> Result<EmitterResult, io::Error> {
const CONTEXT_SIZE: usize = 3;
let mismatch = make_diff(original_text, formatted_text, CONTEXT_SIZE);
Expand Down
4 changes: 3 additions & 1 deletion src/emitter/files.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use super::*;
use crate::NewlineStyle;
use std::fs;

#[derive(Debug, Default)]
Expand All @@ -15,14 +16,15 @@ impl FilesEmitter {
}

impl Emitter for FilesEmitter {
fn emit_formatted_file(
fn emit_formatted_file_with_line_style(
&mut self,
output: &mut dyn Write,
FormattedFile {
filename,
original_text,
formatted_text,
}: FormattedFile<'_>,
_: NewlineStyle,
) -> Result<EmitterResult, io::Error> {
// Write text directly over original file if there is a diff.
let filename = ensure_real_path(filename);
Expand Down
4 changes: 3 additions & 1 deletion src/emitter/files_with_backup.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,20 @@
use super::*;
use crate::NewlineStyle;
use std::fs;

#[derive(Debug, Default)]
pub(crate) struct FilesWithBackupEmitter;

impl Emitter for FilesWithBackupEmitter {
fn emit_formatted_file(
fn emit_formatted_file_with_line_style(
&mut self,
_output: &mut dyn Write,
FormattedFile {
filename,
original_text,
formatted_text,
}: FormattedFile<'_>,
_: NewlineStyle,
) -> Result<EmitterResult, io::Error> {
let filename = ensure_real_path(filename);
if original_text != formatted_text {
Expand Down
36 changes: 30 additions & 6 deletions src/emitter/json.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
use super::*;
use crate::rustfmt_diff::{make_diff, DiffLine, Mismatch};
use crate::NewlineStyle;
use serde::Serialize;
use serde_json::to_string as to_json_string;
use std::io::{self, Write};

use crate::formatting::newline_style::{
apply_newline_style, get_newline_string, get_newline_string_of_text,
};

#[derive(Debug, Default)]
pub(crate) struct JsonEmitter {
mismatched_files: Vec<MismatchedFile>,
Expand All @@ -30,21 +35,25 @@ impl Emitter for JsonEmitter {
writeln!(output, "{}", &to_json_string(&self.mismatched_files)?)
}

fn emit_formatted_file(
fn emit_formatted_file_with_line_style(
&mut self,
_output: &mut dyn Write,
FormattedFile {
filename,
original_text,
formatted_text,
}: FormattedFile<'_>,
newline_style: NewlineStyle,
) -> Result<EmitterResult, io::Error> {
const CONTEXT_SIZE: usize = 0;
let diff = make_diff(original_text, formatted_text, CONTEXT_SIZE);
let has_diff = !diff.is_empty();

let mut formatted_text_string = String::from(formatted_text);
apply_newline_style(newline_style, &mut formatted_text_string, &original_text);

if has_diff {
self.add_misformatted_file(filename, diff)?;
self.add_misformatted_file(filename, diff, newline_style, &original_text)?;
}

Ok(EmitterResult { has_diff })
Expand All @@ -56,8 +65,13 @@ impl JsonEmitter {
&mut self,
filename: &FileName,
diff: Vec<Mismatch>,
newline_style: NewlineStyle,
raw_input_text: &str,
) -> Result<(), io::Error> {
let mut mismatches = vec![];
let expected_newline = get_newline_string(newline_style, raw_input_text);
let origin_newline = get_newline_string_of_text(raw_input_text);

for mismatch in diff {
let original_begin_line = mismatch.line_number_orig;
let expected_begin_line = mismatch.line_number;
Expand All @@ -74,13 +88,13 @@ impl JsonEmitter {
expected_end_line = expected_begin_line + expected_line_counter;
expected_line_counter += 1;
expected.push_str(&msg);
expected.push('\n');
expected.push_str(&expected_newline);
}
DiffLine::Resulting(msg) => {
original_end_line = original_begin_line + original_line_counter;
original_line_counter += 1;
original.push_str(&msg);
original.push('\n');
original.push_str(&origin_newline);
}
DiffLine::Context(_) => continue,
}
Expand Down Expand Up @@ -139,7 +153,12 @@ mod tests {
};

let _ = emitter
.add_misformatted_file(&FileName::Real(PathBuf::from(file)), vec![mismatch])
.add_misformatted_file(
&FileName::Real(PathBuf::from(file)),
vec![mismatch],
NewlineStyle::Auto,
&mismatched_file.mismatches[0].original,
)
.unwrap();

assert_eq!(emitter.mismatched_files.len(), 1);
Expand Down Expand Up @@ -184,7 +203,12 @@ mod tests {
};

let _ = emitter
.add_misformatted_file(&FileName::Real(PathBuf::from(file)), vec![mismatch])
.add_misformatted_file(
&FileName::Real(PathBuf::from(file)),
vec![mismatch],
NewlineStyle::Auto,
&mismatched_file.mismatches[0].original,
)
.unwrap();

assert_eq!(emitter.mismatched_files.len(), 1);
Expand Down
4 changes: 3 additions & 1 deletion src/emitter/modified_lines.rs
Original file line number Diff line number Diff line change
@@ -1,19 +1,21 @@
use super::*;
use crate::rustfmt_diff::{make_diff, ModifiedLines};
use crate::NewlineStyle;
use std::io::Write;

#[derive(Debug, Default)]
pub(crate) struct ModifiedLinesEmitter;

impl Emitter for ModifiedLinesEmitter {
fn emit_formatted_file(
fn emit_formatted_file_with_line_style(
&mut self,
output: &mut dyn Write,
FormattedFile {
original_text,
formatted_text,
..
}: FormattedFile<'_>,
_: NewlineStyle,
) -> Result<EmitterResult, io::Error> {
const CONTEXT_SIZE: usize = 0;
let mismatch = make_diff(original_text, formatted_text, CONTEXT_SIZE);
Expand Down
4 changes: 3 additions & 1 deletion src/emitter/stdout.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use super::*;
use crate::config::Verbosity;
use crate::NewlineStyle;
use std::io::Write;

#[derive(Debug)]
Expand All @@ -14,14 +15,15 @@ impl StdoutEmitter {
}

impl Emitter for StdoutEmitter {
fn emit_formatted_file(
fn emit_formatted_file_with_line_style(
&mut self,
output: &mut dyn Write,
FormattedFile {
filename,
formatted_text,
..
}: FormattedFile<'_>,
_: NewlineStyle,
) -> Result<EmitterResult, io::Error> {
if self.verbosity != Verbosity::Quiet {
writeln!(output, "{}:\n", filename)?;
Expand Down
2 changes: 1 addition & 1 deletion src/formatting.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ use crate::visitor::FmtVisitor;
use crate::{modules, source_file, ErrorKind, FormatReport, Input, Session};

mod generated;
mod newline_style;
pub(crate) mod newline_style;

// A map of the files of a crate, with their new content
pub(crate) type SourceFile = Vec<FileRecord>;
Expand Down
26 changes: 21 additions & 5 deletions src/formatting/newline_style.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
use crate::NewlineStyle;

const LINE_FEED: char = '\n';
const CARRIAGE_RETURN: char = '\r';
const WINDOWS_NEWLINE: &str = "\r\n";
const UNIX_NEWLINE: &str = "\n";

/// 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.
Expand All @@ -17,6 +22,22 @@ pub(crate) fn apply_newline_style(
}
}

/// Get the newline string based on the requested style and the original text
pub(crate) fn get_newline_string(newline_style: NewlineStyle, raw_input_text: &str) -> String {
match effective_newline_style(newline_style, raw_input_text) {
EffectiveNewlineStyle::Windows => WINDOWS_NEWLINE.to_string(),
_ => UNIX_NEWLINE.to_string(),
}
}

/// Get the newline string based on input original text
pub(crate) fn get_newline_string_of_text(raw_input_text: &str) -> String {
match auto_detect_newline_style(raw_input_text) {
EffectiveNewlineStyle::Windows => WINDOWS_NEWLINE.to_string(),
_ => UNIX_NEWLINE.to_string(),
}
}

#[derive(Debug, Copy, Clone, PartialEq, Eq)]
enum EffectiveNewlineStyle {
Windows,
Expand All @@ -35,11 +56,6 @@ fn effective_newline_style(
}
}

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 {
Expand Down
2 changes: 1 addition & 1 deletion src/source_file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,5 +101,5 @@ where
formatted_text,
};

emitter.emit_formatted_file(out, formatted_file)
emitter.emit_formatted_file_with_line_style(out, formatted_file, newline_style)
}
17 changes: 17 additions & 0 deletions src/test/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1051,3 +1051,20 @@ fn verify_check_l_works_with_stdin() {
assert!(output.status.success());
assert_eq!(std::str::from_utf8(&output.stdout).unwrap(), "<stdin>\n");
}

// Test proper Json output Line-style
#[test]
fn emits_json_with_newline_type_unix() {
init_log();
let filename = "tests/writemode/source/json-newline-style-unix.rs";
let expected_filename = "tests/writemode/target/json-newline-style-unix.json";
assert_output(Path::new(filename), Path::new(expected_filename));
}

#[test]
fn emits_json_with_newline_type_windows() {
init_log();
let filename = "tests/writemode/source/json-newline-style-windows.rs";
let expected_filename = "tests/writemode/target/json-newline-style-windows.json";
assert_output(Path::new(filename), Path::new(expected_filename));
}
12 changes: 12 additions & 0 deletions tests/writemode/source/json-newline-style-unix.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// rustfmt-emit_mode: json
// rustfmt-newline_style: Unix

fn main() {
println!("bar");
}
fn main() {
x = y;
}
fn main() {
x = y;
}
12 changes: 12 additions & 0 deletions tests/writemode/source/json-newline-style-windows.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// rustfmt-emit_mode: json
// rustfmt-newline_style: Windows

fn main() {
println!("bar");
}
fn main() {
x = y;
}
fn main() {
x = y;
}
1 change: 1 addition & 0 deletions tests/writemode/target/json-newline-style-unix.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
[{"name":"tests/writemode/source/json-newline-style-unix.rs","mismatches":[{"original_begin_line":5,"original_end_line":5,"expected_begin_line":5,"expected_end_line":5,"original":"println!(\"bar\");\n","expected":" println!(\"bar\");\n"},{"original_begin_line":8,"original_end_line":8,"expected_begin_line":8,"expected_end_line":8,"original":"\tx = y;\n","expected":" x = y;\n"},{"original_begin_line":11,"original_end_line":11,"expected_begin_line":11,"expected_end_line":11,"original":"x = y;\n","expected":" x = y;\n"}]}]
1 change: 1 addition & 0 deletions tests/writemode/target/json-newline-style-windows.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
[{"name":"tests/writemode/source/json-newline-style-windows.rs","mismatches":[{"original_begin_line":5,"original_end_line":5,"expected_begin_line":5,"expected_end_line":5,"original":"println!(\"bar\");\n","expected":" println!(\"bar\");\r\n"},{"original_begin_line":8,"original_end_line":8,"expected_begin_line":8,"expected_end_line":8,"original":"\tx = y;\n","expected":" x = y;\r\n"},{"original_begin_line":11,"original_end_line":11,"expected_begin_line":11,"expected_end_line":11,"original":"x = y;\n","expected":" x = y;\r\n"}]}]