rust/rustfmt-core/src/filemap.rs

186 lines
6.0 KiB
Rust
Raw Normal View History

// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// TODO: add tests
2015-08-02 14:49:35 +02:00
use std::fs::{self, File};
use std::io::{self, BufWriter, Read, Write};
use std::path::Path;
use checkstyle::{output_checkstyle_file, output_footer, output_header};
use config::{Config, NewlineStyle, WriteMode};
Add a new get_modified_lines() API to get only the new changed lines from rustfmting. Squashed commit of the following: commit e90f9da64bbdb640b8c9ee61c3ad395617d8b4da Author: Chris Emerson <github@mail.nosreme.org> Date: Sat Jan 20 20:10:16 2018 +0000 Fix tests after merging with master. commit c3af0042769fe459b0c9c94a0934605ea4b40e40 Merge: 03868583 e0e3e222 Author: Chris Emerson <github@mail.nosreme.org> Date: Sat Jan 20 17:45:05 2018 +0000 Merge remote-tracking branch 'origin/master' into HEAD commit 03868583f8555aae30bdfb5839a82afd3704f4cb Author: Chris Emerson <github@mail.nosreme.org> Date: Mon Nov 20 01:57:56 2017 +0000 Fix some warnings. commit 162b13463e44c782394d418db5ca5710931beb7a Author: Chris Emerson <github@mail.nosreme.org> Date: Mon Nov 20 01:48:02 2017 +0000 Remove unneeded import. commit 20cce3cbfd0f386d92b80bf4c7b83ab4d78a73e7 Merge: 81e98147 fa794f58 Author: Chris Emerson <github@mail.nosreme.org> Date: Mon Nov 20 01:07:17 2017 +0000 Merge branch 'master' into difflines_mode commit 81e981472ceb3a0938d6f050edf8dcd5ebff8e33 Author: Chris Emerson <github@mail.nosreme.org> Date: Mon Nov 20 01:02:50 2017 +0000 Add a simple "modified lines" test. commit 018390ced3523ca9fdd5384a6c1004cdb99174a9 Author: Chris Emerson <github@mail.nosreme.org> Date: Thu Nov 2 23:06:21 2017 +0000 Update test output. commit 7909f4986ed21999aff7b3d075332e686ac464ff Author: Chris Emerson <github@mail.nosreme.org> Date: Thu Nov 2 23:03:22 2017 +0000 Rerun rustfmt. commit 6275f1a8da52db1df36c4b7432996cdbb94ca463 Merge: 7a66d286 175c0c6f Author: Chris Emerson <github@mail.nosreme.org> Date: Thu Nov 2 21:40:29 2017 +0000 Merge remote-tracking branch 'origin/master' into difflines_mode commit 7a66d2866432c430b046938bb37bf5efc03fa9da Author: Chris Emerson <github@mail.nosreme.org> Date: Thu Nov 2 21:36:40 2017 +0000 WIP: Add a separate API to get changed lines. Currently calls format_input() and adjusts the output. commit c8163a923c7d9ae42fd8078cd9b2b51c6f73e36e Author: Chris Emerson <github@mail.nosreme.org> Date: Fri Oct 27 22:53:33 2017 +0100 Remove "modified" from the documentation again. commit 94041fa115a6f428afe40e01d41bf2fe603f70bb Merge: acaa3c7c 2adf7eec Author: Chris Emerson <github@mail.nosreme.org> Date: Fri Oct 27 22:47:05 2017 +0100 Merge branch 'master' into difflines_mode commit acaa3c7ce446297cd3fe5c9610763629a2d8537c Author: Chris Emerson <github@mail.nosreme.org> Date: Tue Oct 24 23:34:14 2017 +0100 Update the Modified write mode to use `out` instead of just prinln!(). This means we can test it more easily, so do so. commit 9f1bbca1f3c12d933ea823918cc548e69b438b1e Author: Chris Emerson <github@mail.nosreme.org> Date: Tue Oct 24 23:11:55 2017 +0100 Add "Modified" to the various lists of modes. commit e12f023756cf3daf202dcaa02bd6492b0d2a0455 Author: Chris Emerson <github@mail.nosreme.org> Date: Tue Oct 24 22:57:33 2017 +0100 Rerun cargo fmt. commit 0f8a43630fa1548e95dcb1c0933708f9c11ae135 Author: Chris Emerson <github@mail.nosreme.org> Date: Tue Oct 24 22:46:26 2017 +0100 Add `line_number_orig` to instances of `Mismatch` in tests. commit d432a7061f74dbc159584f08470c64985a4b41d9 Author: Chris Emerson <github@mail.nosreme.org> Date: Tue Oct 24 22:41:40 2017 +0100 Add a `line_number_orig` field to `Mismatch` to track the pre-format line number. Use that for the write-mode=modified output. commit bdb7d1d23f02f7b8f18e7073a65be88ff94cdbb3 Author: Chris Emerson <github@mail.nosreme.org> Date: Tue Oct 24 22:35:50 2017 +0100 First basic --write-mode=modified implementation. commit ea1433dae0c32879a31182c11be08b1bf53fbf31 Author: Chris Emerson <github@mail.nosreme.org> Date: Fri Oct 20 00:04:16 2017 +0100 WIP on new "modified" mode. commit 27ee9483cf937a11a0e115f54de0afcc3f9ceb44 Merge: e48dd81a 2a84352d Author: Chris Emerson <github@mail.nosreme.org> Date: Tue Oct 24 21:56:44 2017 +0100 Merge remote-tracking branch 'jc/diff_zero_context' into difflines_mode
2018-01-20 20:23:25 +00:00
use rustfmt_diff::{make_diff, output_modified, print_diff, Mismatch};
use syntax::codemap::FileName;
2018-02-07 22:48:05 +09:00
use FileRecord;
// Append a newline to the end of each file.
2017-12-10 17:40:51 +09:00
pub fn append_newline(s: &mut String) {
s.push_str("\n");
}
2017-11-30 15:04:19 +01:00
pub fn write_all_files<T>(
file_map: &[FileRecord],
out: &mut T,
config: &Config,
) -> Result<(), io::Error>
where
T: Write,
{
output_header(out, config.write_mode()).ok();
for &(ref filename, ref text) in file_map {
2017-05-08 13:13:49 +09:00
write_file(text, filename, out, config)?;
}
output_footer(out, config.write_mode()).ok();
Ok(())
}
// Prints all newlines either as `\n` or as `\r\n`.
2017-12-12 13:48:12 +09:00
pub fn write_system_newlines<T>(writer: T, text: &str, config: &Config) -> Result<(), io::Error>
where
T: Write,
{
// Buffer output, since we're writing a since char at a time.
let mut writer = BufWriter::new(writer);
let style = if config.newline_style() == NewlineStyle::Native {
if cfg!(windows) {
NewlineStyle::Windows
} else {
NewlineStyle::Unix
}
} else {
config.newline_style()
};
match style {
NewlineStyle::Unix => write!(writer, "{}", text),
NewlineStyle::Windows => {
2017-12-10 17:40:51 +09:00
for c in text.chars() {
match c {
2017-05-08 13:13:49 +09:00
'\n' => write!(writer, "\r\n")?,
'\r' => continue,
2017-05-08 13:13:49 +09:00
c => write!(writer, "{}", c)?,
2015-08-16 15:58:17 +12:00
}
}
Ok(())
2015-08-16 15:58:17 +12:00
}
NewlineStyle::Native => unreachable!(),
}
}
pub fn write_file<T>(
2017-12-12 13:48:12 +09:00
text: &str,
filename: &FileName,
out: &mut T,
config: &Config,
) -> Result<bool, io::Error>
where
T: Write,
{
fn source_and_formatted_text(
2017-12-12 13:48:12 +09:00
text: &str,
filename: &Path,
config: &Config,
) -> Result<(String, String), io::Error> {
2017-05-08 13:13:49 +09:00
let mut f = File::open(filename)?;
let mut ori_text = String::new();
2017-05-08 13:13:49 +09:00
f.read_to_string(&mut ori_text)?;
let mut v = Vec::new();
2017-05-08 13:13:49 +09:00
write_system_newlines(&mut v, text, config)?;
let fmt_text = String::from_utf8(v).unwrap();
Ok((ori_text, fmt_text))
}
fn create_diff(
filename: &Path,
2017-12-12 13:48:12 +09:00
text: &str,
config: &Config,
) -> Result<Vec<Mismatch>, io::Error> {
2017-05-08 13:13:49 +09:00
let (ori, fmt) = source_and_formatted_text(text, filename, config)?;
Ok(make_diff(&ori, &fmt, 3))
}
let filename_to_path = || match *filename {
FileName::Real(ref path) => path,
_ => panic!("cannot format `{}` with WriteMode::Replace", filename),
};
match config.write_mode() {
2015-08-18 21:10:30 +02:00
WriteMode::Replace => {
let filename = filename_to_path();
if let Ok((ori, fmt)) = source_and_formatted_text(text, filename, config) {
if fmt != ori {
// Do a little dance to make writing safer - write to a temp file
// rename the original to a .bk, then rename the temp file to the
// original.
let tmp_name = filename.with_extension("tmp");
let bk_name = filename.with_extension("bk");
{
// Write text to temp file
2017-05-08 13:13:49 +09:00
let tmp_file = File::create(&tmp_name)?;
write_system_newlines(tmp_file, text, config)?;
}
2015-08-18 21:10:30 +02:00
2017-05-08 13:13:49 +09:00
fs::rename(filename, bk_name)?;
fs::rename(tmp_name, filename)?;
}
}
}
2015-08-18 21:10:30 +02:00
WriteMode::Overwrite => {
// Write text directly over original file if there is a diff.
let filename = filename_to_path();
let (source, formatted) = source_and_formatted_text(text, filename, config)?;
if source != formatted {
let file = File::create(filename)?;
write_system_newlines(file, text, config)?;
}
2015-08-18 21:10:30 +02:00
}
WriteMode::Plain => {
2017-05-08 13:13:49 +09:00
write_system_newlines(out, text, config)?;
}
2015-10-21 12:56:24 +05:30
WriteMode::Display | WriteMode::Coverage => {
2015-08-18 21:10:30 +02:00
println!("{}:\n", filename);
2017-05-08 13:13:49 +09:00
write_system_newlines(out, text, config)?;
2015-08-18 21:10:30 +02:00
}
WriteMode::Diff => {
let filename = filename_to_path();
if let Ok((ori, fmt)) = source_and_formatted_text(text, filename, config) {
let mismatch = make_diff(&ori, &fmt, 3);
let has_diff = !mismatch.is_empty();
2017-11-10 07:23:12 +11:00
print_diff(
mismatch,
|line_num| format!("Diff in {} at line {}:", filename.display(), line_num),
2017-11-10 07:23:12 +11:00
config.color(),
);
return Ok(has_diff);
}
}
Add a new get_modified_lines() API to get only the new changed lines from rustfmting. Squashed commit of the following: commit e90f9da64bbdb640b8c9ee61c3ad395617d8b4da Author: Chris Emerson <github@mail.nosreme.org> Date: Sat Jan 20 20:10:16 2018 +0000 Fix tests after merging with master. commit c3af0042769fe459b0c9c94a0934605ea4b40e40 Merge: 03868583 e0e3e222 Author: Chris Emerson <github@mail.nosreme.org> Date: Sat Jan 20 17:45:05 2018 +0000 Merge remote-tracking branch 'origin/master' into HEAD commit 03868583f8555aae30bdfb5839a82afd3704f4cb Author: Chris Emerson <github@mail.nosreme.org> Date: Mon Nov 20 01:57:56 2017 +0000 Fix some warnings. commit 162b13463e44c782394d418db5ca5710931beb7a Author: Chris Emerson <github@mail.nosreme.org> Date: Mon Nov 20 01:48:02 2017 +0000 Remove unneeded import. commit 20cce3cbfd0f386d92b80bf4c7b83ab4d78a73e7 Merge: 81e98147 fa794f58 Author: Chris Emerson <github@mail.nosreme.org> Date: Mon Nov 20 01:07:17 2017 +0000 Merge branch 'master' into difflines_mode commit 81e981472ceb3a0938d6f050edf8dcd5ebff8e33 Author: Chris Emerson <github@mail.nosreme.org> Date: Mon Nov 20 01:02:50 2017 +0000 Add a simple "modified lines" test. commit 018390ced3523ca9fdd5384a6c1004cdb99174a9 Author: Chris Emerson <github@mail.nosreme.org> Date: Thu Nov 2 23:06:21 2017 +0000 Update test output. commit 7909f4986ed21999aff7b3d075332e686ac464ff Author: Chris Emerson <github@mail.nosreme.org> Date: Thu Nov 2 23:03:22 2017 +0000 Rerun rustfmt. commit 6275f1a8da52db1df36c4b7432996cdbb94ca463 Merge: 7a66d286 175c0c6f Author: Chris Emerson <github@mail.nosreme.org> Date: Thu Nov 2 21:40:29 2017 +0000 Merge remote-tracking branch 'origin/master' into difflines_mode commit 7a66d2866432c430b046938bb37bf5efc03fa9da Author: Chris Emerson <github@mail.nosreme.org> Date: Thu Nov 2 21:36:40 2017 +0000 WIP: Add a separate API to get changed lines. Currently calls format_input() and adjusts the output. commit c8163a923c7d9ae42fd8078cd9b2b51c6f73e36e Author: Chris Emerson <github@mail.nosreme.org> Date: Fri Oct 27 22:53:33 2017 +0100 Remove "modified" from the documentation again. commit 94041fa115a6f428afe40e01d41bf2fe603f70bb Merge: acaa3c7c 2adf7eec Author: Chris Emerson <github@mail.nosreme.org> Date: Fri Oct 27 22:47:05 2017 +0100 Merge branch 'master' into difflines_mode commit acaa3c7ce446297cd3fe5c9610763629a2d8537c Author: Chris Emerson <github@mail.nosreme.org> Date: Tue Oct 24 23:34:14 2017 +0100 Update the Modified write mode to use `out` instead of just prinln!(). This means we can test it more easily, so do so. commit 9f1bbca1f3c12d933ea823918cc548e69b438b1e Author: Chris Emerson <github@mail.nosreme.org> Date: Tue Oct 24 23:11:55 2017 +0100 Add "Modified" to the various lists of modes. commit e12f023756cf3daf202dcaa02bd6492b0d2a0455 Author: Chris Emerson <github@mail.nosreme.org> Date: Tue Oct 24 22:57:33 2017 +0100 Rerun cargo fmt. commit 0f8a43630fa1548e95dcb1c0933708f9c11ae135 Author: Chris Emerson <github@mail.nosreme.org> Date: Tue Oct 24 22:46:26 2017 +0100 Add `line_number_orig` to instances of `Mismatch` in tests. commit d432a7061f74dbc159584f08470c64985a4b41d9 Author: Chris Emerson <github@mail.nosreme.org> Date: Tue Oct 24 22:41:40 2017 +0100 Add a `line_number_orig` field to `Mismatch` to track the pre-format line number. Use that for the write-mode=modified output. commit bdb7d1d23f02f7b8f18e7073a65be88ff94cdbb3 Author: Chris Emerson <github@mail.nosreme.org> Date: Tue Oct 24 22:35:50 2017 +0100 First basic --write-mode=modified implementation. commit ea1433dae0c32879a31182c11be08b1bf53fbf31 Author: Chris Emerson <github@mail.nosreme.org> Date: Fri Oct 20 00:04:16 2017 +0100 WIP on new "modified" mode. commit 27ee9483cf937a11a0e115f54de0afcc3f9ceb44 Merge: e48dd81a 2a84352d Author: Chris Emerson <github@mail.nosreme.org> Date: Tue Oct 24 21:56:44 2017 +0100 Merge remote-tracking branch 'jc/diff_zero_context' into difflines_mode
2018-01-20 20:23:25 +00:00
WriteMode::Modified => {
let filename = filename_to_path();
if let Ok((ori, fmt)) = source_and_formatted_text(text, filename, config) {
let mismatch = make_diff(&ori, &fmt, 0);
let has_diff = !mismatch.is_empty();
output_modified(out, mismatch);
return Ok(has_diff);
}
}
WriteMode::Checkstyle => {
let filename = filename_to_path();
let diff = create_diff(filename, text, config)?;
2017-05-08 13:13:49 +09:00
output_checkstyle_file(out, filename, diff)?;
}
2015-08-18 21:10:30 +02:00
}
// when we are not in diff mode, don't indicate differing files
Ok(false)
}