rust/src/lib.rs

1035 lines
33 KiB
Rust
Raw Normal View History

// Copyright 2015-2018 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.
#![feature(custom_attribute)]
#![feature(decl_macro)]
// FIXME(cramertj) remove after match_default_bindings merges
#![allow(stable_features)]
#![allow(unused_attributes)]
#![feature(match_default_bindings)]
#![feature(type_ascription)]
#![feature(unicode_internals)]
2015-04-13 20:00:46 -05:00
2017-11-06 06:44:59 -06:00
#[macro_use]
extern crate derive_new;
2017-08-08 10:16:35 -05:00
extern crate diff;
#[macro_use]
2018-04-24 03:10:09 -05:00
extern crate failure;
extern crate getopts;
extern crate itertools;
#[cfg(test)]
#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate log;
2017-08-08 10:16:35 -05:00
extern crate regex;
extern crate rustc_target;
extern crate serde;
#[macro_use]
extern crate serde_derive;
extern crate serde_json;
2017-08-08 10:16:35 -05:00
extern crate syntax;
extern crate term;
extern crate toml;
2017-08-08 10:16:35 -05:00
extern crate unicode_segmentation;
2015-09-03 22:38:12 -05:00
use std::collections::HashMap;
use std::fmt;
2018-04-20 05:10:48 -05:00
use std::io::{self, stdout, Write};
use std::panic::{catch_unwind, AssertUnwindSafe};
use std::path::PathBuf;
2016-03-01 16:27:19 -06:00
use std::rc::Rc;
2017-11-17 07:21:46 -06:00
use std::time::Duration;
use syntax::ast;
pub use syntax::codemap::FileName;
2018-03-14 02:43:01 -05:00
use syntax::codemap::{CodeMap, FilePathMapping};
use syntax::errors::emitter::{ColorConfig, EmitterWriter};
2018-03-16 02:57:35 -05:00
use syntax::errors::{DiagnosticBuilder, Handler};
use syntax::parse::{self, ParseSess};
use comment::{CharClasses, FullCodeCharKind, LineClasses};
2018-04-24 03:10:09 -05:00
use failure::Fail;
use issues::{BadIssueSeeker, Issue};
use shape::Indent;
use utils::use_colored_tty;
use visitor::{FmtVisitor, SnippetProvider};
pub use config::options::CliOptions;
2018-02-07 08:15:00 -06:00
pub use config::summary::Summary;
pub use config::{file_lines, load_config, Config, Verbosity, WriteMode};
pub type FmtResult<T> = std::result::Result<T, failure::Error>;
2015-06-08 13:23:24 -05:00
#[macro_use]
mod utils;
2018-02-17 10:06:54 -06:00
2018-02-23 07:30:05 -06:00
mod attr;
mod chains;
pub(crate) mod checkstyle;
2017-11-12 20:26:33 -06:00
mod closures;
pub(crate) mod codemap;
mod comment;
pub(crate) mod config;
2015-04-21 04:01:19 -05:00
mod expr;
pub(crate) mod filemap;
2015-04-21 04:01:19 -05:00
mod imports;
mod issues;
mod items;
mod lists;
2015-09-14 15:53:30 -05:00
mod macros;
mod matches;
mod missed_spans;
pub(crate) mod modules;
mod overflow;
2015-10-17 08:56:53 -05:00
mod patterns;
2018-02-17 10:06:54 -06:00
mod reorder;
mod rewrite;
pub(crate) mod rustfmt_diff;
mod shape;
mod spanned;
mod string;
#[cfg(test)]
mod test;
mod types;
mod vertical;
pub(crate) mod visitor;
2018-02-22 18:07:35 -06:00
const STDIN: &str = "<stdin>";
2018-02-07 07:48:05 -06:00
// A map of the files of a crate, with their new content
pub(crate) type FileMap = Vec<FileRecord>;
2018-02-07 07:48:05 -06:00
pub(crate) type FileRecord = (FileName, String);
2018-02-07 07:48:05 -06:00
2018-04-24 03:10:09 -05:00
#[derive(Fail, Debug, Clone, Copy)]
pub enum ErrorKind {
// Line has exceeded character limit (found, maximum)
2018-04-24 03:10:09 -05:00
#[fail(
2018-05-06 02:17:09 -05:00
display = "line formatted, but exceeded maximum width \
(maximum: {} (see `max_width` option), found: {})",
2018-04-24 03:10:09 -05:00
_0,
_1
)]
LineOverflow(usize, usize),
// Line ends in whitespace
2018-04-24 03:10:09 -05:00
#[fail(display = "left behind trailing whitespace")]
TrailingWhitespace,
// TODO or FIXME item without an issue number
2018-04-24 03:10:09 -05:00
#[fail(display = "found {}", _0)]
BadIssue(Issue),
Attempt at checking for license (#209) I'm not quite sure how best to handle loading the license template from a path -- I mean obviously I know *how* to do it, but I'm not sure where to fit it in the codebase :) So this first attempt puts the license template directly into the config file. These are my misgivings about the license template config option as a path to a file (I'd love feedback if some of these are wrong or can be easily circumvented!): 1. I thought the obvious choice for the type of `license_template` in `create_config!` should be `PathBuf`, but `PathBuf` doesn't implement `FromStr` (yet? see https://github.com/rust-lang/rust/issues/44431), so it would have to be wrapped in a tuple struct, and I went down that road for a little while but then it seemed like too much ceremony for too little gain. 2. So a plain `String` then (which, mind you, also means the same `doc_hint()`, i.e. `<string>`, not `<path>` or something like that). The fact that it's a valid path will be checked once we try to read the file. 3. But where in the code should the license template be read? The obvious choice for me would be somewhere in `Config::from_toml()`, but since `Config` is defined via the `create_config!` macro, that would mean tight coupling between the macro invocation (which defines the configuration option `license_template`) and its definition (which would rely on the existence of that option to run the template loading code). 4. `license_template` could also be made a special option which is hardwired into the macro. This gets rid of the tight coupling, but special-casing one of the config options would make the code harder to navigate. 5. Instead, the macro could maybe be rewritten to allow for config options that load additional resources from files when the config is being parsed, but that's beyond my skill level I'm afraid (and probably overengineering the problem if it's only ever going to be used for this one option). 6. Finally, the file can be loaded at some later point in time, e.g. in `format_lines()`, right before `check_license()` is called. But to face a potential *IO* error at so late a stage, when the source files have already been parsed... I don't know, it doesn't feel right. BTW I don't like that I'm actually parsing the license template as late as inside `check_license()` either, but for much the same reasons, I don't know where else to put it. If the `Config` were hand-rolled instead of a macro, I'd just define a custom `license_template` option and load and parse the template in the `Config`'s init. But the way things are, I'm a bit at a loss. However, if someone more familiar with the project would kindly provide a few hints as to how the path approach can be done in a way that is as clean as possible in the context of the codebase, I'll be more than happy to implement it! :)
2018-02-16 16:21:57 -06:00
// License check has failed
2018-04-24 03:10:09 -05:00
#[fail(display = "license check failed")]
Attempt at checking for license (#209) I'm not quite sure how best to handle loading the license template from a path -- I mean obviously I know *how* to do it, but I'm not sure where to fit it in the codebase :) So this first attempt puts the license template directly into the config file. These are my misgivings about the license template config option as a path to a file (I'd love feedback if some of these are wrong or can be easily circumvented!): 1. I thought the obvious choice for the type of `license_template` in `create_config!` should be `PathBuf`, but `PathBuf` doesn't implement `FromStr` (yet? see https://github.com/rust-lang/rust/issues/44431), so it would have to be wrapped in a tuple struct, and I went down that road for a little while but then it seemed like too much ceremony for too little gain. 2. So a plain `String` then (which, mind you, also means the same `doc_hint()`, i.e. `<string>`, not `<path>` or something like that). The fact that it's a valid path will be checked once we try to read the file. 3. But where in the code should the license template be read? The obvious choice for me would be somewhere in `Config::from_toml()`, but since `Config` is defined via the `create_config!` macro, that would mean tight coupling between the macro invocation (which defines the configuration option `license_template`) and its definition (which would rely on the existence of that option to run the template loading code). 4. `license_template` could also be made a special option which is hardwired into the macro. This gets rid of the tight coupling, but special-casing one of the config options would make the code harder to navigate. 5. Instead, the macro could maybe be rewritten to allow for config options that load additional resources from files when the config is being parsed, but that's beyond my skill level I'm afraid (and probably overengineering the problem if it's only ever going to be used for this one option). 6. Finally, the file can be loaded at some later point in time, e.g. in `format_lines()`, right before `check_license()` is called. But to face a potential *IO* error at so late a stage, when the source files have already been parsed... I don't know, it doesn't feel right. BTW I don't like that I'm actually parsing the license template as late as inside `check_license()` either, but for much the same reasons, I don't know where else to put it. If the `Config` were hand-rolled instead of a macro, I'd just define a custom `license_template` option and load and parse the template in the `Config`'s init. But the way things are, I'm a bit at a loss. However, if someone more familiar with the project would kindly provide a few hints as to how the path approach can be done in a way that is as clean as possible in the context of the codebase, I'll be more than happy to implement it! :)
2018-02-16 16:21:57 -06:00
LicenseCheck,
}
// Formatting errors that are identified *after* rustfmt has run.
struct FormattingError {
line: usize,
kind: ErrorKind,
is_comment: bool,
is_string: bool,
line_buffer: String,
}
impl FormattingError {
fn msg_prefix(&self) -> &str {
match self.kind {
ErrorKind::LineOverflow(..) | ErrorKind::TrailingWhitespace => "internal error:",
ErrorKind::LicenseCheck => "error:",
ErrorKind::BadIssue(_) => "warning:",
}
}
fn msg_suffix(&self) -> &str {
if self.is_comment || self.is_string {
"set `error_on_unformatted = false` to suppress \
the warning against comments or string literals\n"
} else {
""
}
}
// (space, target)
fn format_len(&self) -> (usize, usize) {
match self.kind {
ErrorKind::LineOverflow(found, max) => (max, found - max),
ErrorKind::TrailingWhitespace => {
2018-05-07 16:25:48 -05:00
let trailing_ws_start = self
.line_buffer
.rfind(|c: char| !c.is_whitespace())
.map(|pos| pos + 1)
.unwrap_or(0);
(
trailing_ws_start,
self.line_buffer.len() - trailing_ws_start,
)
}
_ => unreachable!(),
}
}
}
pub struct FormatReport {
// Maps stringified file paths to their associated formatting errors.
file_error_map: HashMap<FileName, Vec<FormattingError>>,
}
impl FormatReport {
fn new() -> FormatReport {
2017-07-03 04:54:26 -05:00
FormatReport {
file_error_map: HashMap::new(),
}
}
fn warning_count(&self) -> usize {
self.file_error_map
.iter()
.map(|(_, errors)| errors.len())
2018-01-25 23:53:28 -06:00
.sum()
}
fn has_warnings(&self) -> bool {
self.warning_count() > 0
}
fn print_warnings_fancy(
&self,
mut t: Box<term::Terminal<Output = io::Stderr>>,
) -> Result<(), term::Error> {
for (file, errors) in &self.file_error_map {
for error in errors {
let prefix_space_len = error.line.to_string().len();
2018-04-01 02:20:46 -05:00
let prefix_spaces = " ".repeat(1 + prefix_space_len);
// First line: the overview of error
t.fg(term::color::RED)?;
t.attr(term::Attr::Bold)?;
write!(t, "{} ", error.msg_prefix())?;
t.reset()?;
t.attr(term::Attr::Bold)?;
2018-04-24 17:21:23 -05:00
writeln!(t, "{}", error.kind)?;
// Second line: file info
write!(t, "{}--> ", &prefix_spaces[1..])?;
t.reset()?;
2018-04-24 17:21:23 -05:00
writeln!(t, "{}:{}", file, error.line)?;
// Third to fifth lines: show the line which triggered error, if available.
if !error.line_buffer.is_empty() {
let (space_len, target_len) = error.format_len();
t.attr(term::Attr::Bold)?;
write!(t, "{}|\n{} | ", prefix_spaces, error.line)?;
t.reset()?;
2018-04-24 17:21:23 -05:00
writeln!(t, "{}", error.line_buffer)?;
t.attr(term::Attr::Bold)?;
write!(t, "{}| ", prefix_spaces)?;
t.fg(term::color::RED)?;
2018-04-24 17:21:23 -05:00
writeln!(t, "{}", target_str(space_len, target_len))?;
t.reset()?;
}
// The last line: show note if available.
let msg_suffix = error.msg_suffix();
if !msg_suffix.is_empty() {
t.attr(term::Attr::Bold)?;
write!(t, "{}= note: ", prefix_spaces)?;
t.reset()?;
2018-04-24 17:21:23 -05:00
writeln!(t, "{}", error.msg_suffix())?;
} else {
2018-04-24 17:21:23 -05:00
writeln!(t)?;
}
t.reset()?;
}
}
if !self.file_error_map.is_empty() {
t.attr(term::Attr::Bold)?;
write!(t, "warning: ")?;
t.reset()?;
write!(
t,
"rustfmt may have failed to format. See previous {} errors.\n\n",
self.warning_count(),
)?;
}
Ok(())
}
}
fn target_str(space_len: usize, target_len: usize) -> String {
2018-04-01 02:20:46 -05:00
let empty_line = " ".repeat(space_len);
let overflowed = "^".repeat(target_len);
empty_line + &overflowed
}
impl fmt::Display for FormatReport {
// Prints all the formatting errors.
fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
2015-09-04 16:39:33 -05:00
for (file, errors) in &self.file_error_map {
for error in errors {
let prefix_space_len = error.line.to_string().len();
2018-04-01 02:20:46 -05:00
let prefix_spaces = " ".repeat(1 + prefix_space_len);
let error_line_buffer = if error.line_buffer.is_empty() {
String::from(" ")
} else {
let (space_len, target_len) = error.format_len();
format!(
"{}|\n{} | {}\n{}| {}",
prefix_spaces,
error.line,
error.line_buffer,
prefix_spaces,
target_str(space_len, target_len)
)
};
let error_info = format!("{} {}", error.msg_prefix(), error.kind);
let file_info = format!("{}--> {}:{}", &prefix_spaces[1..], file, error.line);
let msg_suffix = error.msg_suffix();
let note = if msg_suffix.is_empty() {
String::new()
} else {
format!("{}note= ", prefix_spaces)
};
2018-04-24 17:21:23 -05:00
writeln!(
fmt,
2018-04-24 17:21:23 -05:00
"{}\n{}\n{}\n{}{}",
error_info,
file_info,
error_line_buffer,
note,
error.msg_suffix()
)?;
}
}
if !self.file_error_map.is_empty() {
2018-04-24 17:21:23 -05:00
writeln!(
fmt,
2018-04-24 17:21:23 -05:00
"warning: rustfmt may have failed to format. See previous {} errors.",
self.warning_count(),
)?;
}
Ok(())
}
}
fn should_emit_verbose<F>(path: &FileName, config: &Config, f: F)
where
F: Fn(),
{
if config.verbose() == Verbosity::Verbose && path.to_string() != STDIN {
f();
}
}
// Formatting which depends on the AST.
fn format_ast<F>(
krate: &ast::Crate,
2017-08-11 03:54:38 -05:00
parse_session: &mut ParseSess,
main_file: &FileName,
config: &Config,
mut after_file: F,
) -> Result<(FileMap, bool), io::Error>
where
F: FnMut(&FileName, &mut String, &[(usize, usize)]) -> Result<bool, io::Error>,
{
let mut result = FileMap::new();
// diff mode: check if any files are differing
let mut has_diff = false;
let skip_children = config.skip_children();
2017-11-06 06:45:54 -06:00
for (path, module) in modules::list_files(krate, parse_session.codemap())? {
if (skip_children && path != *main_file) || config.ignore().skip_file(&path) {
continue;
}
should_emit_verbose(&path, config, || println!("Formatting {}", path));
let filemap = parse_session
.codemap()
.lookup_char_pos(module.inner.lo())
.file;
let big_snippet = filemap.src.as_ref().unwrap();
let snippet_provider = SnippetProvider::new(filemap.start_pos, big_snippet);
let mut visitor = FmtVisitor::from_codemap(parse_session, config, &snippet_provider);
2017-08-29 22:00:10 -05:00
// Format inner attributes if available.
if !krate.attrs.is_empty() && path == *main_file {
visitor.skip_empty_lines(filemap.end_pos);
if visitor.visit_attrs(&krate.attrs, ast::AttrStyle::Inner) {
visitor.push_rewrite(module.inner, None);
} else {
visitor.format_separate_mod(module, &*filemap);
}
2017-08-29 22:00:10 -05:00
} else {
visitor.last_pos = filemap.start_pos;
visitor.skip_empty_lines(filemap.end_pos);
visitor.format_separate_mod(module, &*filemap);
};
2018-02-18 21:50:39 -06:00
debug_assert_eq!(
2017-12-08 01:59:04 -06:00
visitor.line_number,
2018-04-24 17:21:23 -05:00
::utils::count_newlines(&visitor.buffer)
2017-12-08 01:59:04 -06:00
);
let filename = path.clone();
has_diff |= match after_file(&filename, &mut visitor.buffer, &visitor.skipped_range) {
Ok(result) => result,
Err(e) => {
// Create a new error with path_str to help users see which files failed
let err_msg = format!("{}: {}", path, e);
return Err(io::Error::new(e.kind(), err_msg));
}
};
result.push((filename, visitor.buffer));
}
Ok((result, has_diff))
}
/// Returns true if the line with the given line number was skipped by `#[rustfmt_skip]`.
fn is_skipped_line(line_number: usize, skipped_range: &[(usize, usize)]) -> bool {
skipped_range
.iter()
.any(|&(lo, hi)| lo <= line_number && line_number <= hi)
}
fn should_report_error(
config: &Config,
char_kind: FullCodeCharKind,
is_string: bool,
error_kind: ErrorKind,
) -> bool {
let allow_error_report = if char_kind.is_comment() || is_string {
config.error_on_unformatted()
} else {
true
};
match error_kind {
ErrorKind::LineOverflow(..) => config.error_on_line_overflow() && allow_error_report,
ErrorKind::TrailingWhitespace => allow_error_report,
_ => true,
}
}
2015-04-21 05:50:43 -05:00
// Formatting done on a char by char or line by line basis.
// FIXME(#20) other stuff for parity with make tidy
fn format_lines(
2017-12-10 02:40:51 -06:00
text: &mut String,
name: &FileName,
skipped_range: &[(usize, usize)],
config: &Config,
report: &mut FormatReport,
) {
let mut trims = vec![];
let mut last_wspace: Option<usize> = None;
let mut line_len = 0;
let mut cur_line = 1;
let mut newline_count = 0;
let mut errors = vec![];
let mut issue_seeker = BadIssueSeeker::new(config.report_todo(), config.report_fixme());
let mut line_buffer = String::with_capacity(config.max_width() * 2);
let mut is_string = false; // true if the current line contains a string literal.
let mut format_line = config.file_lines().contains_line(name, cur_line);
2018-02-18 21:50:39 -06:00
let allow_issue_seek = !issue_seeker.is_disabled();
Attempt at checking for license (#209) I'm not quite sure how best to handle loading the license template from a path -- I mean obviously I know *how* to do it, but I'm not sure where to fit it in the codebase :) So this first attempt puts the license template directly into the config file. These are my misgivings about the license template config option as a path to a file (I'd love feedback if some of these are wrong or can be easily circumvented!): 1. I thought the obvious choice for the type of `license_template` in `create_config!` should be `PathBuf`, but `PathBuf` doesn't implement `FromStr` (yet? see https://github.com/rust-lang/rust/issues/44431), so it would have to be wrapped in a tuple struct, and I went down that road for a little while but then it seemed like too much ceremony for too little gain. 2. So a plain `String` then (which, mind you, also means the same `doc_hint()`, i.e. `<string>`, not `<path>` or something like that). The fact that it's a valid path will be checked once we try to read the file. 3. But where in the code should the license template be read? The obvious choice for me would be somewhere in `Config::from_toml()`, but since `Config` is defined via the `create_config!` macro, that would mean tight coupling between the macro invocation (which defines the configuration option `license_template`) and its definition (which would rely on the existence of that option to run the template loading code). 4. `license_template` could also be made a special option which is hardwired into the macro. This gets rid of the tight coupling, but special-casing one of the config options would make the code harder to navigate. 5. Instead, the macro could maybe be rewritten to allow for config options that load additional resources from files when the config is being parsed, but that's beyond my skill level I'm afraid (and probably overengineering the problem if it's only ever going to be used for this one option). 6. Finally, the file can be loaded at some later point in time, e.g. in `format_lines()`, right before `check_license()` is called. But to face a potential *IO* error at so late a stage, when the source files have already been parsed... I don't know, it doesn't feel right. BTW I don't like that I'm actually parsing the license template as late as inside `check_license()` either, but for much the same reasons, I don't know where else to put it. If the `Config` were hand-rolled instead of a macro, I'd just define a custom `license_template` option and load and parse the template in the `Config`'s init. But the way things are, I'm a bit at a loss. However, if someone more familiar with the project would kindly provide a few hints as to how the path approach can be done in a way that is as clean as possible in the context of the codebase, I'll be more than happy to implement it! :)
2018-02-16 16:21:57 -06:00
// Check license.
if let Some(ref license_template) = config.license_template {
if !license_template.is_match(text) {
errors.push(FormattingError {
line: cur_line,
kind: ErrorKind::LicenseCheck,
is_comment: false,
is_string: false,
line_buffer: String::new(),
});
Attempt at checking for license (#209) I'm not quite sure how best to handle loading the license template from a path -- I mean obviously I know *how* to do it, but I'm not sure where to fit it in the codebase :) So this first attempt puts the license template directly into the config file. These are my misgivings about the license template config option as a path to a file (I'd love feedback if some of these are wrong or can be easily circumvented!): 1. I thought the obvious choice for the type of `license_template` in `create_config!` should be `PathBuf`, but `PathBuf` doesn't implement `FromStr` (yet? see https://github.com/rust-lang/rust/issues/44431), so it would have to be wrapped in a tuple struct, and I went down that road for a little while but then it seemed like too much ceremony for too little gain. 2. So a plain `String` then (which, mind you, also means the same `doc_hint()`, i.e. `<string>`, not `<path>` or something like that). The fact that it's a valid path will be checked once we try to read the file. 3. But where in the code should the license template be read? The obvious choice for me would be somewhere in `Config::from_toml()`, but since `Config` is defined via the `create_config!` macro, that would mean tight coupling between the macro invocation (which defines the configuration option `license_template`) and its definition (which would rely on the existence of that option to run the template loading code). 4. `license_template` could also be made a special option which is hardwired into the macro. This gets rid of the tight coupling, but special-casing one of the config options would make the code harder to navigate. 5. Instead, the macro could maybe be rewritten to allow for config options that load additional resources from files when the config is being parsed, but that's beyond my skill level I'm afraid (and probably overengineering the problem if it's only ever going to be used for this one option). 6. Finally, the file can be loaded at some later point in time, e.g. in `format_lines()`, right before `check_license()` is called. But to face a potential *IO* error at so late a stage, when the source files have already been parsed... I don't know, it doesn't feel right. BTW I don't like that I'm actually parsing the license template as late as inside `check_license()` either, but for much the same reasons, I don't know where else to put it. If the `Config` were hand-rolled instead of a macro, I'd just define a custom `license_template` option and load and parse the template in the `Config`'s init. But the way things are, I'm a bit at a loss. However, if someone more familiar with the project would kindly provide a few hints as to how the path approach can be done in a way that is as clean as possible in the context of the codebase, I'll be more than happy to implement it! :)
2018-02-16 16:21:57 -06:00
}
}
// Iterate over the chars in the file map.
2017-12-10 20:50:11 -06:00
for (kind, (b, c)) in CharClasses::new(text.chars().enumerate()) {
if c == '\r' {
continue;
}
2018-02-18 21:50:39 -06:00
if allow_issue_seek && format_line {
// Add warnings for bad todos/ fixmes
if let Some(issue) = issue_seeker.inspect(c) {
2015-09-26 01:29:48 -05:00
errors.push(FormattingError {
line: cur_line,
kind: ErrorKind::BadIssue(issue),
is_comment: false,
is_string: false,
line_buffer: String::new(),
});
}
}
if c == '\n' {
if format_line {
// Check for (and record) trailing whitespace.
if let Some(..) = last_wspace {
if should_report_error(config, kind, is_string, ErrorKind::TrailingWhitespace) {
trims.push((cur_line, kind, line_buffer.clone()));
}
line_len -= 1;
}
// Check for any line width errors we couldn't correct.
let error_kind = ErrorKind::LineOverflow(line_len, config.max_width());
2018-05-06 01:22:29 -05:00
if line_len > config.max_width()
&& !is_skipped_line(cur_line, skipped_range)
&& should_report_error(config, kind, is_string, error_kind)
{
errors.push(FormattingError {
line: cur_line,
kind: error_kind,
is_comment: kind.is_comment(),
2018-01-21 22:05:18 -06:00
is_string,
line_buffer: line_buffer.clone(),
});
}
}
line_len = 0;
cur_line += 1;
format_line = config.file_lines().contains_line(name, cur_line);
newline_count += 1;
last_wspace = None;
line_buffer.clear();
is_string = false;
} else {
newline_count = 0;
line_len += if c == '\t' { config.tab_spaces() } else { 1 };
if c.is_whitespace() {
if last_wspace.is_none() {
last_wspace = Some(b);
}
} else {
last_wspace = None;
}
line_buffer.push(c);
if kind.is_string() {
is_string = true;
}
}
}
if newline_count > 1 {
2017-12-10 02:40:51 -06:00
debug!("track truncate: {} {}", text.len(), newline_count);
let line = text.len() - newline_count + 1;
text.truncate(line);
}
2015-04-23 01:02:55 -05:00
for &(l, kind, ref b) in &trims {
if !is_skipped_line(l, skipped_range) {
errors.push(FormattingError {
line: l,
kind: ErrorKind::TrailingWhitespace,
is_comment: kind.is_comment(),
is_string: kind.is_string(),
line_buffer: b.clone(),
});
}
2015-04-23 01:02:55 -05:00
}
report.file_error_map.insert(name.clone(), errors);
}
fn parse_input<'sess>(
input: Input,
parse_session: &'sess ParseSess,
config: &Config,
) -> Result<ast::Crate, ParseError<'sess>> {
let mut parser = match input {
Input::File(file) => parse::new_parser_from_file(parse_session, &file),
Input::Text(text) => parse::new_parser_from_source_str(
parse_session,
FileName::Custom("stdin".to_owned()),
text,
),
};
parser.cfg_mods = false;
if config.skip_children() {
parser.recurse_into_file_modules = false;
}
let mut parser = AssertUnwindSafe(parser);
let result = catch_unwind(move || parser.0.parse_crate_mod());
2016-05-17 16:58:51 -05:00
match result {
Ok(Ok(c)) => {
2016-05-17 16:58:51 -05:00
if parse_session.span_diagnostic.has_errors() {
// Bail out if the parser recovered from an error.
Err(ParseError::Recovered)
2016-05-17 16:58:51 -05:00
} else {
Ok(c)
}
}
Ok(Err(e)) => Err(ParseError::Error(e)),
Err(_) => Err(ParseError::Panic),
}
}
/// All the ways that parsing can fail.
enum ParseError<'sess> {
/// There was an error, but the parser recovered.
Recovered,
/// There was an error (supplied) and parsing failed.
Error(DiagnosticBuilder<'sess>),
/// The parser panicked.
Panic,
}
/// Format the given snippet. The snippet is expected to be *complete* code.
/// When we cannot parse the given snippet, this function returns `None`.
pub fn format_snippet(snippet: &str, config: &Config) -> Option<String> {
let mut out: Vec<u8> = Vec::with_capacity(snippet.len() * 2);
let input = Input::Text(snippet.into());
let mut config = config.clone();
config.set().write_mode(config::WriteMode::Display);
config.set().verbose(Verbosity::Quiet);
2018-01-11 00:19:23 -06:00
config.set().hide_parse_errors(true);
match format_input(input, &config, Some(&mut out)) {
// `format_input()` returns an empty string on parsing error.
Ok(..) if out.is_empty() && !snippet.is_empty() => None,
Ok(..) => String::from_utf8(out).ok(),
Err(..) => None,
}
}
const FN_MAIN_PREFIX: &str = "fn main() {\n";
fn enclose_in_main_block(s: &str, config: &Config) -> String {
let indent = Indent::from_width(config, config.tab_spaces());
let mut result = String::with_capacity(s.len() * 2);
result.push_str(FN_MAIN_PREFIX);
let mut need_indent = true;
for (kind, line) in LineClasses::new(s) {
if need_indent {
result.push_str(&indent.to_string(config));
}
result.push_str(&line);
result.push('\n');
2018-04-24 17:21:23 -05:00
need_indent = !kind.is_string() || line.ends_with('\\');
}
result.push('}');
result
}
/// Format the given code block. Mainly targeted for code block in comment.
/// The code block may be incomplete (i.e. parser may be unable to parse it).
/// To avoid panic in parser, we wrap the code block with a dummy function.
/// The returned code block does *not* end with newline.
pub fn format_code_block(code_snippet: &str, config: &Config) -> Option<String> {
// Wrap the given code block with `fn main()` if it does not have one.
let snippet = enclose_in_main_block(code_snippet, config);
let mut result = String::with_capacity(snippet.len());
let mut is_first = true;
// Trim "fn main() {" on the first line and "}" on the last line,
// then unindent the whole code block.
let formatted = format_snippet(&snippet, config)?;
// 2 = "}\n"
let block_len = formatted.rfind('}').unwrap_or(formatted.len());
let mut is_indented = true;
for (kind, ref line) in LineClasses::new(&formatted[FN_MAIN_PREFIX.len()..block_len]) {
if !is_first {
result.push('\n');
} else {
is_first = false;
}
let trimmed_line = if !is_indented {
line
} else if line.len() > config.max_width() {
// If there are lines that are larger than max width, we cannot tell
// whether we have succeeded but have some comments or strings that
// are too long, or we have failed to format code block. We will be
// conservative and just return `None` in this case.
return None;
} else if line.len() > config.tab_spaces() {
// Make sure that the line has leading whitespaces.
let indent_str = Indent::from_width(config, config.tab_spaces()).to_string(config);
if line.starts_with(indent_str.as_ref()) {
let offset = if config.hard_tabs() {
1
} else {
config.tab_spaces()
};
&line[offset..]
} else {
line
}
} else {
line
};
result.push_str(trimmed_line);
2018-04-24 17:21:23 -05:00
is_indented = !kind.is_string() || line.ends_with('\\');
}
Some(result)
}
pub fn format_input<T: Write>(
input: Input,
config: &Config,
out: Option<&mut T>,
) -> Result<(Summary, FileMap, FormatReport), (io::Error, Summary)> {
syntax::with_globals(|| format_input_inner(input, config, out))
}
fn format_input_inner<T: Write>(
input: Input,
config: &Config,
mut out: Option<&mut T>,
) -> Result<(Summary, FileMap, FormatReport), (io::Error, Summary)> {
2017-08-29 08:16:04 -05:00
let mut summary = Summary::default();
if config.disable_all_formatting() {
// When the input is from stdin, echo back the input.
if let Input::Text(ref buf) = input {
if let Err(e) = io::stdout().write_all(buf.as_bytes()) {
return Err((e, summary));
}
}
return Ok((summary, FileMap::new(), FormatReport::new()));
}
let codemap = Rc::new(CodeMap::new(FilePathMapping::empty()));
2016-03-01 16:27:19 -06:00
let tty_handler = if config.hide_parse_errors() {
let silent_emitter = Box::new(EmitterWriter::new(
Box::new(Vec::new()),
Some(codemap.clone()),
false,
2018-02-01 19:18:30 -06:00
false,
));
Handler::with_emitter(true, false, silent_emitter)
} else {
let supports_color = term::stderr().map_or(false, |term| term.supports_color());
let color_cfg = if supports_color {
ColorConfig::Auto
} else {
ColorConfig::Never
};
Handler::with_tty_emitter(color_cfg, true, false, Some(codemap.clone()))
};
2016-03-01 16:27:19 -06:00
let mut parse_session = ParseSess::with_span_handler(tty_handler, codemap.clone());
2016-04-11 11:49:56 -05:00
let main_file = match input {
Input::File(ref file) => FileName::Real(file.clone()),
Input::Text(..) => FileName::Custom("stdin".to_owned()),
2016-04-11 11:49:56 -05:00
};
let krate = match parse_input(input, &parse_session, config) {
2016-04-11 11:49:56 -05:00
Ok(krate) => krate,
Err(err) => {
match err {
ParseError::Error(mut diagnostic) => diagnostic.emit(),
ParseError::Panic => {
// Note that if you see this message and want more information,
// then go to `parse_input` and run the parse function without
// `catch_unwind` so rustfmt panics and you can get a backtrace.
should_emit_verbose(&main_file, config, || {
println!("The Rust parser panicked")
});
}
ParseError::Recovered => {}
}
summary.add_parsing_error();
return Ok((summary, FileMap::new(), FormatReport::new()));
2016-04-11 11:49:56 -05:00
}
};
summary.mark_parse_time();
// Suppress error output after parsing.
let silent_emitter = Box::new(EmitterWriter::new(
Box::new(Vec::new()),
Some(codemap.clone()),
2017-10-20 08:53:06 -05:00
false,
2018-02-01 19:18:30 -06:00
false,
));
2016-03-01 16:27:19 -06:00
parse_session.span_diagnostic = Handler::with_emitter(true, false, silent_emitter);
let mut report = FormatReport::new();
let format_result = format_ast(
2017-05-31 22:08:09 -05:00
&krate,
&mut parse_session,
2017-05-31 22:08:09 -05:00
&main_file,
config,
|file_name, file, skipped_range| {
2017-05-31 22:08:09 -05:00
// For some reason, the codemap does not include terminating
// newlines so we must add one on for each file. This is sad.
filemap::append_newline(file);
format_lines(file, file_name, skipped_range, config, &mut report);
2017-05-31 22:08:09 -05:00
if let Some(ref mut out) = out {
return filemap::write_file(file, file_name, out, config);
}
Ok(false)
2017-06-03 08:50:44 -05:00
},
);
summary.mark_format_time();
should_emit_verbose(&main_file, config, || {
2017-11-17 07:21:46 -06:00
fn duration_to_f32(d: Duration) -> f32 {
d.as_secs() as f32 + d.subsec_nanos() as f32 / 1_000_000_000f32
}
println!(
2017-11-17 07:21:46 -06:00
"Spent {0:.3} secs in the parsing phase, and {1:.3} secs in the formatting phase",
duration_to_f32(summary.get_parse_time().unwrap()),
duration_to_f32(summary.get_format_time().unwrap()),
)
});
match format_result {
Ok((file_map, has_diff)) => {
if report.has_warnings() {
summary.add_formatting_error();
}
if has_diff {
summary.add_diff();
}
Ok((summary, file_map, report))
}
Err(e) => Err((e, summary)),
}
2016-04-02 13:56:37 -05:00
}
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 14:23:25 -06:00
/// A single span of changed lines, with 0 or more removed lines
/// and a vector of 0 or more inserted lines.
#[derive(Debug, PartialEq, Eq)]
2018-04-20 05:10:48 -05:00
struct ModifiedChunk {
2018-02-12 17:07:46 -06:00
/// The first to be removed from the original text
pub line_number_orig: u32,
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 14:23:25 -06:00
/// The number of lines which have been replaced
pub lines_removed: u32,
/// The new lines
pub lines: Vec<String>,
}
/// Set of changed sections of a file.
#[derive(Debug, PartialEq, Eq)]
2018-04-20 05:10:48 -05:00
struct ModifiedLines {
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 14:23:25 -06:00
/// The set of changed chunks.
pub chunks: Vec<ModifiedChunk>,
}
2018-02-22 18:07:35 -06:00
/// The successful result of formatting via `get_modified_lines()`.
2018-04-20 05:10:48 -05:00
#[cfg(test)]
struct ModifiedLinesResult {
/// The high level summary details
pub summary: Summary,
/// The result Filemap
pub filemap: FileMap,
/// Map of formatting errors
pub report: FormatReport,
/// The sets of updated lines.
pub modified_lines: ModifiedLines,
}
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 14:23:25 -06:00
/// Format a file and return a `ModifiedLines` data structure describing
/// the changed ranges of lines.
2018-04-20 05:10:48 -05:00
#[cfg(test)]
fn get_modified_lines(
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 14:23:25 -06:00
input: Input,
config: &Config,
) -> Result<ModifiedLinesResult, (io::Error, Summary)> {
2018-04-20 05:10:48 -05:00
use std::io::BufRead;
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 14:23:25 -06:00
let mut data = Vec::new();
let mut config = config.clone();
config.set().write_mode(config::WriteMode::Modified);
2018-03-08 01:29:00 -06:00
let (summary, filemap, report) = format_input(input, &config, Some(&mut data))?;
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 14:23:25 -06:00
let mut lines = data.lines();
let mut chunks = Vec::new();
while let Some(Ok(header)) = lines.next() {
// Parse the header line
let values: Vec<_> = header
.split(' ')
.map(|s| s.parse::<u32>().unwrap())
.collect();
assert_eq!(values.len(), 3);
2018-02-12 17:07:46 -06:00
let line_number_orig = values[0];
let lines_removed = values[1];
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 14:23:25 -06:00
let num_added = values[2];
let mut added_lines = Vec::new();
for _ in 0..num_added {
added_lines.push(lines.next().unwrap().unwrap());
}
chunks.push(ModifiedChunk {
2018-02-12 17:07:46 -06:00
line_number_orig,
lines_removed,
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 14:23:25 -06:00
lines: added_lines,
});
}
Ok(ModifiedLinesResult {
2018-03-08 01:29:00 -06:00
summary,
filemap,
report,
2018-02-12 17:07:46 -06:00
modified_lines: ModifiedLines { chunks },
})
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 14:23:25 -06:00
}
2016-05-25 13:41:26 -05:00
#[derive(Debug)]
2016-04-02 13:56:37 -05:00
pub enum Input {
File(PathBuf),
Text(String),
}
pub fn format_and_emit_report(input: Input, config: &Config) -> FmtResult<Summary> {
if !config.version_meets_requirement() {
return Err(format_err!("Version mismatch"));
}
2017-08-11 03:54:38 -05:00
let out = &mut stdout();
match format_input(input, config, Some(out)) {
Ok((summary, _, report)) => {
if report.has_warnings() {
match term::stderr() {
Some(ref t)
2018-05-06 01:22:29 -05:00
if use_colored_tty(config.color())
&& t.supports_color()
2017-11-09 14:23:12 -06:00
&& t.supports_attr(term::Attr::Bold) =>
{
match report.print_warnings_fancy(term::stderr().unwrap()) {
Ok(..) => (),
Err(..) => panic!("Unable to write to stderr: {}", report),
}
}
_ => eprintln!("{}", report),
}
}
Ok(summary)
}
Err((msg, mut summary)) => {
eprintln!("Error writing files: {}", msg);
summary.add_operational_error();
Ok(summary)
}
}
}
pub fn emit_pre_matter(config: &Config) -> FmtResult<()> {
if config.write_mode() == WriteMode::Checkstyle {
let mut out = &mut stdout();
checkstyle::output_header(&mut out)?;
}
Ok(())
}
pub fn emit_post_matter(config: &Config) -> FmtResult<()> {
if config.write_mode() == WriteMode::Checkstyle {
let mut out = &mut stdout();
checkstyle::output_footer(&mut out)?;
}
Ok(())
}
#[cfg(test)]
mod unit_tests {
use super::{format_code_block, format_snippet, Config};
#[test]
fn test_no_panic_on_format_snippet_and_format_code_block() {
// `format_snippet()` and `format_code_block()` should not panic
// even when we cannot parse the given snippet.
let snippet = "let";
assert!(format_snippet(snippet, &Config::default()).is_none());
assert!(format_code_block(snippet, &Config::default()).is_none());
}
fn test_format_inner<F>(formatter: F, input: &str, expected: &str) -> bool
where
F: Fn(&str, &Config) -> Option<String>,
{
let output = formatter(input, &Config::default());
output.is_some() && output.unwrap() == expected
}
#[test]
fn test_format_snippet() {
let snippet = "fn main() { println!(\"hello, world\"); }";
let expected = "fn main() {\n \
println!(\"hello, world\");\n\
}\n";
assert!(test_format_inner(format_snippet, snippet, expected));
}
#[test]
fn test_format_code_block_fail() {
#[rustfmt_skip]
let code_block = "this_line_is_100_characters_long_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx(x, y, z);";
assert!(format_code_block(code_block, &Config::default()).is_none());
}
#[test]
fn test_format_code_block() {
// simple code block
let code_block = "let x=3;";
let expected = "let x = 3;";
assert!(test_format_inner(format_code_block, code_block, expected));
// more complex code block, taken from chains.rs.
let code_block =
"let (nested_shape, extend) = if !parent_rewrite_contains_newline && is_continuable(&parent) {
(
chain_indent(context, shape.add_offset(parent_rewrite.len())),
context.config.indent_style() == IndentStyle::Visual || is_small_parent,
)
} else if is_block_expr(context, &parent, &parent_rewrite) {
match context.config.indent_style() {
// Try to put the first child on the same line with parent's last line
IndentStyle::Block => (parent_shape.block_indent(context.config.tab_spaces()), true),
// The parent is a block, so align the rest of the chain with the closing
// brace.
IndentStyle::Visual => (parent_shape, false),
}
} else {
(
chain_indent(context, shape.add_offset(parent_rewrite.len())),
false,
)
};
";
let expected =
"let (nested_shape, extend) = if !parent_rewrite_contains_newline && is_continuable(&parent) {
(
chain_indent(context, shape.add_offset(parent_rewrite.len())),
context.config.indent_style() == IndentStyle::Visual || is_small_parent,
)
} else if is_block_expr(context, &parent, &parent_rewrite) {
match context.config.indent_style() {
// Try to put the first child on the same line with parent's last line
IndentStyle::Block => (parent_shape.block_indent(context.config.tab_spaces()), true),
// The parent is a block, so align the rest of the chain with the closing
// brace.
IndentStyle::Visual => (parent_shape, false),
}
} else {
(
chain_indent(context, shape.add_offset(parent_rewrite.len())),
false,
)
};";
assert!(test_format_inner(format_code_block, code_block, expected));
}
}