Move from String to PathBuf where applicable
This commit is contained in:
parent
4ee7911f4b
commit
fad903fd14
@ -8,6 +8,7 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![feature(rustc_private)]
|
||||
#![cfg(not(test))]
|
||||
|
||||
extern crate env_logger;
|
||||
@ -22,7 +23,7 @@ use std::str::FromStr;
|
||||
|
||||
use getopts::{Matches, Options};
|
||||
|
||||
use rustfmt::{run, Input, Summary};
|
||||
use rustfmt::{run, FileName, Input, Summary};
|
||||
use rustfmt::file_lines::FileLines;
|
||||
use rustfmt::config::{get_toml_path, Color, Config, WriteMode};
|
||||
|
||||
@ -243,8 +244,9 @@ fn execute(opts: &Options) -> FmtResult<Summary> {
|
||||
if let Some(ref file_lines) = matches.opt_str("file-lines") {
|
||||
config.set().file_lines(file_lines.parse()?);
|
||||
for f in config.file_lines().files() {
|
||||
if f != "stdin" {
|
||||
eprintln!("Warning: Extra file listed in file_lines option '{}'", f);
|
||||
match *f {
|
||||
FileName::Custom(ref f) if f == "stdin" => {}
|
||||
_ => eprintln!("Warning: Extra file listed in file_lines option '{}'", f),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -264,8 +266,12 @@ fn execute(opts: &Options) -> FmtResult<Summary> {
|
||||
let options = CliOptions::from_matches(&matches)?;
|
||||
|
||||
for f in options.file_lines.files() {
|
||||
if !files.contains(&PathBuf::from(f)) {
|
||||
eprintln!("Warning: Extra file listed in file_lines option '{}'", f);
|
||||
match *f {
|
||||
FileName::Real(ref f) if files.contains(f) => {}
|
||||
FileName::Real(_) => {
|
||||
eprintln!("Warning: Extra file listed in file_lines option '{}'", f)
|
||||
}
|
||||
_ => eprintln!("Warning: Not a file '{}'", f),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -9,6 +9,7 @@
|
||||
// except according to those terms.
|
||||
|
||||
use std::io::{self, Write};
|
||||
use std::path::Path;
|
||||
|
||||
use config::WriteMode;
|
||||
use rustfmt_diff::{DiffLine, Mismatch};
|
||||
@ -41,13 +42,13 @@ where
|
||||
|
||||
pub fn output_checkstyle_file<T>(
|
||||
mut writer: T,
|
||||
filename: &str,
|
||||
filename: &Path,
|
||||
diff: Vec<Mismatch>,
|
||||
) -> Result<(), io::Error>
|
||||
where
|
||||
T: Write,
|
||||
{
|
||||
write!(writer, "<file name=\"{}\">", filename)?;
|
||||
write!(writer, "<file name=\"{}\">", filename.display())?;
|
||||
for mismatch in diff {
|
||||
for line in mismatch.lines {
|
||||
// Do nothing with `DiffLine::Context` and `DiffLine::Resulting`.
|
||||
|
@ -13,7 +13,7 @@
|
||||
|
||||
use std::rc::Rc;
|
||||
|
||||
use syntax::codemap::{BytePos, CodeMap, FileMap, Span};
|
||||
use syntax::codemap::{BytePos, CodeMap, FileMap, FileName, Span};
|
||||
|
||||
use comment::FindUncommented;
|
||||
|
||||
@ -25,8 +25,8 @@ pub struct LineRange {
|
||||
}
|
||||
|
||||
impl LineRange {
|
||||
pub fn file_name(&self) -> &str {
|
||||
self.file.as_ref().name.as_str()
|
||||
pub fn file_name(&self) -> &FileName {
|
||||
&self.file.name
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -10,12 +10,14 @@
|
||||
|
||||
//! This module contains types and functions to support formatting specific line ranges.
|
||||
|
||||
use std::{cmp, iter, path, str};
|
||||
use std::{cmp, iter, str};
|
||||
use std::collections::HashMap;
|
||||
|
||||
use serde::de::{Deserialize, Deserializer};
|
||||
use serde_json as json;
|
||||
|
||||
use codemap::LineRange;
|
||||
use syntax::codemap::FileName;
|
||||
|
||||
/// A range that is inclusive of both ends.
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq, PartialOrd, Ord, Deserialize)]
|
||||
@ -84,11 +86,11 @@ impl Range {
|
||||
/// non-overlapping ranges sorted by their start point. An inner `None` is interpreted to mean all
|
||||
/// lines in all files.
|
||||
#[derive(Clone, Debug, Default)]
|
||||
pub struct FileLines(Option<HashMap<String, Vec<Range>>>);
|
||||
pub struct FileLines(Option<HashMap<FileName, Vec<Range>>>);
|
||||
|
||||
/// Normalizes the ranges so that the invariants for `FileLines` hold: ranges are non-overlapping,
|
||||
/// and ordered by their start point.
|
||||
fn normalize_ranges(ranges: &mut HashMap<String, Vec<Range>>) {
|
||||
fn normalize_ranges(ranges: &mut HashMap<FileName, Vec<Range>>) {
|
||||
for ranges in ranges.values_mut() {
|
||||
ranges.sort();
|
||||
let mut result = vec![];
|
||||
@ -117,7 +119,7 @@ impl FileLines {
|
||||
FileLines(None)
|
||||
}
|
||||
|
||||
pub fn from_ranges(mut ranges: HashMap<String, Vec<Range>>) -> FileLines {
|
||||
pub fn from_ranges(mut ranges: HashMap<FileName, Vec<Range>>) -> FileLines {
|
||||
normalize_ranges(&mut ranges);
|
||||
FileLines(Some(ranges))
|
||||
}
|
||||
@ -129,7 +131,7 @@ impl FileLines {
|
||||
|
||||
/// Returns true if `self` includes all lines in all files. Otherwise runs `f` on all ranges in
|
||||
/// the designated file (if any) and returns true if `f` ever does.
|
||||
fn file_range_matches<F>(&self, file_name: &str, f: F) -> bool
|
||||
fn file_range_matches<F>(&self, file_name: &FileName, f: F) -> bool
|
||||
where
|
||||
F: FnMut(&Range) -> bool,
|
||||
{
|
||||
@ -156,35 +158,31 @@ impl FileLines {
|
||||
}
|
||||
|
||||
/// Returns true if `line` from `file_name` is in `self`.
|
||||
pub fn contains_line(&self, file_name: &str, line: usize) -> bool {
|
||||
pub fn contains_line(&self, file_name: &FileName, line: usize) -> bool {
|
||||
self.file_range_matches(file_name, |r| r.lo <= line && r.hi >= line)
|
||||
}
|
||||
|
||||
/// Returns true if any of the lines between `lo` and `hi` from `file_name` are in `self`.
|
||||
pub fn intersects_range(&self, file_name: &str, lo: usize, hi: usize) -> bool {
|
||||
pub fn intersects_range(&self, file_name: &FileName, lo: usize, hi: usize) -> bool {
|
||||
self.file_range_matches(file_name, |r| r.intersects(Range::new(lo, hi)))
|
||||
}
|
||||
}
|
||||
|
||||
/// `FileLines` files iterator.
|
||||
pub struct Files<'a>(Option<::std::collections::hash_map::Keys<'a, String, Vec<Range>>>);
|
||||
pub struct Files<'a>(Option<::std::collections::hash_map::Keys<'a, FileName, Vec<Range>>>);
|
||||
|
||||
impl<'a> iter::Iterator for Files<'a> {
|
||||
type Item = &'a String;
|
||||
type Item = &'a FileName;
|
||||
|
||||
fn next(&mut self) -> Option<&'a String> {
|
||||
fn next(&mut self) -> Option<&'a FileName> {
|
||||
self.0.as_mut().and_then(Iterator::next)
|
||||
}
|
||||
}
|
||||
|
||||
fn canonicalize_path_string(s: &str) -> Option<String> {
|
||||
if s == "stdin" {
|
||||
return Some(s.to_string());
|
||||
}
|
||||
|
||||
match path::PathBuf::from(s).canonicalize() {
|
||||
Ok(canonicalized) => canonicalized.to_str().map(|s| s.to_string()),
|
||||
_ => None,
|
||||
fn canonicalize_path_string(file: &FileName) -> Option<FileName> {
|
||||
match *file {
|
||||
FileName::Real(ref path) => path.canonicalize().ok().map(FileName::Real),
|
||||
_ => Some(file.clone()),
|
||||
}
|
||||
}
|
||||
|
||||
@ -206,12 +204,21 @@ impl str::FromStr for FileLines {
|
||||
// For JSON decoding.
|
||||
#[derive(Clone, Debug, Deserialize)]
|
||||
struct JsonSpan {
|
||||
file: String,
|
||||
#[serde(deserialize_with = "deserialize_filename")] file: FileName,
|
||||
range: (usize, usize),
|
||||
}
|
||||
|
||||
fn deserialize_filename<'de, D: Deserializer<'de>>(d: D) -> Result<FileName, D::Error> {
|
||||
let s = String::deserialize(d)?;
|
||||
if s == "stdin" {
|
||||
Ok(FileName::Custom(s))
|
||||
} else {
|
||||
Ok(FileName::Real(s.into()))
|
||||
}
|
||||
}
|
||||
|
||||
impl JsonSpan {
|
||||
fn into_tuple(self) -> Result<(String, Range), String> {
|
||||
fn into_tuple(self) -> Result<(FileName, Range), String> {
|
||||
let (lo, hi) = self.range;
|
||||
let canonical = canonicalize_path_string(&self.file)
|
||||
.ok_or_else(|| format!("Can't canonicalize {}", &self.file))?;
|
||||
|
@ -12,15 +12,17 @@
|
||||
|
||||
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};
|
||||
use rustfmt_diff::{make_diff, print_diff, Mismatch};
|
||||
use syntax::codemap::FileName;
|
||||
|
||||
// A map of the files of a crate, with their new content
|
||||
pub type FileMap = Vec<FileRecord>;
|
||||
|
||||
pub type FileRecord = (String, String);
|
||||
pub type FileRecord = (FileName, String);
|
||||
|
||||
// Append a newline to the end of each file.
|
||||
pub fn append_newline(s: &mut String) {
|
||||
@ -80,7 +82,7 @@ where
|
||||
|
||||
pub fn write_file<T>(
|
||||
text: &str,
|
||||
filename: &str,
|
||||
filename: &FileName,
|
||||
out: &mut T,
|
||||
config: &Config,
|
||||
) -> Result<bool, io::Error>
|
||||
@ -89,7 +91,7 @@ where
|
||||
{
|
||||
fn source_and_formatted_text(
|
||||
text: &str,
|
||||
filename: &str,
|
||||
filename: &Path,
|
||||
config: &Config,
|
||||
) -> Result<(String, String), io::Error> {
|
||||
let mut f = File::open(filename)?;
|
||||
@ -102,7 +104,7 @@ where
|
||||
}
|
||||
|
||||
fn create_diff(
|
||||
filename: &str,
|
||||
filename: &Path,
|
||||
text: &str,
|
||||
config: &Config,
|
||||
) -> Result<Vec<Mismatch>, io::Error> {
|
||||
@ -110,15 +112,21 @@ where
|
||||
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() {
|
||||
WriteMode::Replace => {
|
||||
if let Ok((ori, fmt)) = source_and_formatted_text(text, filename, config) {
|
||||
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.to_owned() + ".tmp";
|
||||
let bk_name = filename.to_owned() + ".bk";
|
||||
let tmp_name = filename.with_extension("tmp");
|
||||
let bk_name = filename.with_extension("bk");
|
||||
{
|
||||
// Write text to temp file
|
||||
let tmp_file = File::create(&tmp_name)?;
|
||||
@ -132,7 +140,8 @@ where
|
||||
}
|
||||
WriteMode::Overwrite => {
|
||||
// Write text directly over original file if there is a diff.
|
||||
let (source, formatted) = source_and_formatted_text(text, filename, config)?;
|
||||
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)?;
|
||||
@ -146,19 +155,21 @@ where
|
||||
write_system_newlines(out, text, config)?;
|
||||
}
|
||||
WriteMode::Diff => {
|
||||
if let Ok((ori, fmt)) = source_and_formatted_text(text, filename, config) {
|
||||
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();
|
||||
print_diff(
|
||||
mismatch,
|
||||
|line_num| format!("Diff in {} at line {}:", filename, line_num),
|
||||
|line_num| format!("Diff in {} at line {}:", filename.display(), line_num),
|
||||
config.color(),
|
||||
);
|
||||
return Ok(has_diff);
|
||||
}
|
||||
}
|
||||
WriteMode::Checkstyle => {
|
||||
let diff = create_diff(filename, text, config)?;
|
||||
let filename = filename_to_path();
|
||||
let diff = create_diff(&filename, text, config)?;
|
||||
output_checkstyle_file(out, filename, diff)?;
|
||||
}
|
||||
}
|
||||
|
38
src/lib.rs
38
src/lib.rs
@ -29,13 +29,14 @@ use std::collections::HashMap;
|
||||
use std::fmt;
|
||||
use std::io::{self, stdout, Write};
|
||||
use std::iter::repeat;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::path::PathBuf;
|
||||
use std::rc::Rc;
|
||||
|
||||
use errors::{DiagnosticBuilder, Handler};
|
||||
use errors::emitter::{ColorConfig, EmitterWriter};
|
||||
use syntax::ast;
|
||||
use syntax::codemap::{CodeMap, FilePathMapping};
|
||||
pub use syntax::codemap::FileName;
|
||||
use syntax::parse::{self, ParseSess};
|
||||
|
||||
use checkstyle::{output_footer, output_header};
|
||||
@ -146,7 +147,7 @@ impl FormattingError {
|
||||
|
||||
pub struct FormatReport {
|
||||
// Maps stringified file paths to their associated formatting errors.
|
||||
file_error_map: HashMap<String, Vec<FormattingError>>,
|
||||
file_error_map: HashMap<FileName, Vec<FormattingError>>,
|
||||
}
|
||||
|
||||
impl FormatReport {
|
||||
@ -295,12 +296,12 @@ impl fmt::Display for FormatReport {
|
||||
fn format_ast<F>(
|
||||
krate: &ast::Crate,
|
||||
parse_session: &mut ParseSess,
|
||||
main_file: &Path,
|
||||
main_file: &FileName,
|
||||
config: &Config,
|
||||
mut after_file: F,
|
||||
) -> Result<(FileMap, bool), io::Error>
|
||||
where
|
||||
F: FnMut(&str, &mut String, &[(usize, usize)]) -> Result<bool, io::Error>,
|
||||
F: FnMut(&FileName, &mut String, &[(usize, usize)]) -> Result<bool, io::Error>,
|
||||
{
|
||||
let mut result = FileMap::new();
|
||||
// diff mode: check if any files are differing
|
||||
@ -310,12 +311,11 @@ where
|
||||
// nothing to distinguish the nested module contents.
|
||||
let skip_children = config.skip_children() || config.write_mode() == config::WriteMode::Plain;
|
||||
for (path, module) in modules::list_files(krate, parse_session.codemap())? {
|
||||
if skip_children && path.as_path() != main_file {
|
||||
if skip_children && path != *main_file {
|
||||
continue;
|
||||
}
|
||||
let path_str = path.to_str().unwrap();
|
||||
if config.verbose() {
|
||||
println!("Formatting {}", path_str);
|
||||
println!("Formatting {}", path);
|
||||
}
|
||||
let filemap = parse_session
|
||||
.codemap()
|
||||
@ -325,7 +325,7 @@ where
|
||||
let snippet_provider = SnippetProvider::new(filemap.start_pos, big_snippet);
|
||||
let mut visitor = FmtVisitor::from_codemap(parse_session, config, &snippet_provider);
|
||||
// Format inner attributes if available.
|
||||
if !krate.attrs.is_empty() && path == main_file {
|
||||
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);
|
||||
@ -343,16 +343,17 @@ where
|
||||
::utils::count_newlines(&format!("{}", visitor.buffer))
|
||||
);
|
||||
|
||||
has_diff |= match after_file(path_str, &mut visitor.buffer, &visitor.skipped_range) {
|
||||
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 = path_str.to_string() + &": ".to_string() + &e.to_string();
|
||||
let err_msg = format!("{}: {}", path, e);
|
||||
return Err(io::Error::new(e.kind(), err_msg));
|
||||
}
|
||||
};
|
||||
|
||||
result.push((path_str.to_owned(), visitor.buffer));
|
||||
result.push((filename, visitor.buffer));
|
||||
}
|
||||
|
||||
Ok((result, has_diff))
|
||||
@ -389,7 +390,7 @@ fn should_report_error(
|
||||
// FIXME(#20) other stuff for parity with make tidy
|
||||
fn format_lines(
|
||||
text: &mut String,
|
||||
name: &str,
|
||||
name: &FileName,
|
||||
skipped_range: &[(usize, usize)],
|
||||
config: &Config,
|
||||
report: &mut FormatReport,
|
||||
@ -491,7 +492,7 @@ fn format_lines(
|
||||
}
|
||||
}
|
||||
|
||||
report.file_error_map.insert(name.to_owned(), errors);
|
||||
report.file_error_map.insert(name.clone(), errors);
|
||||
}
|
||||
|
||||
fn parse_input(
|
||||
@ -505,8 +506,11 @@ fn parse_input(
|
||||
parser.parse_crate_mod()
|
||||
}
|
||||
Input::Text(text) => {
|
||||
let mut parser =
|
||||
parse::new_parser_from_source_str(parse_session, "stdin".to_owned(), text);
|
||||
let mut parser = parse::new_parser_from_source_str(
|
||||
parse_session,
|
||||
FileName::Custom("stdin".to_owned()),
|
||||
text,
|
||||
);
|
||||
parser.cfg_mods = false;
|
||||
parser.parse_crate_mod()
|
||||
}
|
||||
@ -547,8 +551,8 @@ pub fn format_input<T: Write>(
|
||||
let mut parse_session = ParseSess::with_span_handler(tty_handler, codemap.clone());
|
||||
|
||||
let main_file = match input {
|
||||
Input::File(ref file) => file.clone(),
|
||||
Input::Text(..) => PathBuf::from("stdin"),
|
||||
Input::File(ref file) => FileName::Real(file.clone()),
|
||||
Input::Text(..) => FileName::Custom("stdin".to_owned()),
|
||||
};
|
||||
|
||||
let krate = match parse_input(input, &parse_session) {
|
||||
|
@ -11,7 +11,7 @@
|
||||
use std::borrow::Cow;
|
||||
use std::iter::repeat;
|
||||
|
||||
use syntax::codemap::{BytePos, Pos, Span};
|
||||
use syntax::codemap::{BytePos, FileName, Pos, Span};
|
||||
|
||||
use codemap::LineRangeUtils;
|
||||
use comment::{rewrite_comment, CodeCharKind, CommentCodeSlices};
|
||||
@ -260,7 +260,7 @@ impl<'a> FmtVisitor<'a> {
|
||||
snippet: &str,
|
||||
subslice: &str,
|
||||
offset: usize,
|
||||
file_name: &str,
|
||||
file_name: &FileName,
|
||||
) {
|
||||
for (mut i, c) in subslice.char_indices() {
|
||||
i += offset;
|
||||
|
@ -13,7 +13,7 @@ use std::path::{Path, PathBuf};
|
||||
use std::io;
|
||||
|
||||
use syntax::ast;
|
||||
use syntax::codemap;
|
||||
use syntax::codemap::{self, FileName};
|
||||
use syntax::parse::parser;
|
||||
|
||||
use utils::contains_skip;
|
||||
@ -23,15 +23,16 @@ use utils::contains_skip;
|
||||
pub fn list_files<'a>(
|
||||
krate: &'a ast::Crate,
|
||||
codemap: &codemap::CodeMap,
|
||||
) -> Result<BTreeMap<PathBuf, &'a ast::Mod>, io::Error> {
|
||||
) -> Result<BTreeMap<FileName, &'a ast::Mod>, io::Error> {
|
||||
let mut result = BTreeMap::new(); // Enforce file order determinism
|
||||
let root_filename: PathBuf = codemap.span_to_filename(krate.span).into();
|
||||
list_submodules(
|
||||
&krate.module,
|
||||
root_filename.parent().unwrap(),
|
||||
codemap,
|
||||
&mut result,
|
||||
)?;
|
||||
let root_filename = codemap.span_to_filename(krate.span);
|
||||
{
|
||||
let parent = match root_filename {
|
||||
FileName::Real(ref path) => path.parent().unwrap(),
|
||||
_ => Path::new(""),
|
||||
};
|
||||
list_submodules(&krate.module, parent, codemap, &mut result)?;
|
||||
}
|
||||
result.insert(root_filename, &krate.module);
|
||||
Ok(result)
|
||||
}
|
||||
@ -41,7 +42,7 @@ fn list_submodules<'a>(
|
||||
module: &'a ast::Mod,
|
||||
search_dir: &Path,
|
||||
codemap: &codemap::CodeMap,
|
||||
result: &mut BTreeMap<PathBuf, &'a ast::Mod>,
|
||||
result: &mut BTreeMap<FileName, &'a ast::Mod>,
|
||||
) -> Result<(), io::Error> {
|
||||
debug!("list_submodules: search_dir: {:?}", search_dir);
|
||||
for item in &module.items {
|
||||
@ -54,7 +55,7 @@ fn list_submodules<'a>(
|
||||
} else {
|
||||
let mod_path = module_file(item.ident, &item.attrs, search_dir, codemap)?;
|
||||
let dir_path = mod_path.parent().unwrap().to_owned();
|
||||
result.insert(mod_path, sub_mod);
|
||||
result.insert(FileName::Real(mod_path), sub_mod);
|
||||
dir_path
|
||||
};
|
||||
list_submodules(sub_mod, &dir_path, codemap, result)?;
|
||||
|
@ -8,6 +8,8 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![feature(rustc_private)]
|
||||
|
||||
#[macro_use]
|
||||
extern crate log;
|
||||
extern crate regex;
|
||||
@ -28,10 +30,8 @@ use rustfmt::rustfmt_diff::*;
|
||||
|
||||
const DIFF_CONTEXT_SIZE: usize = 3;
|
||||
|
||||
fn get_path_string(dir_entry: io::Result<fs::DirEntry>) -> String {
|
||||
let path = dir_entry.expect("Couldn't get DirEntry").path();
|
||||
|
||||
path.to_str().expect("Couldn't stringify path").to_owned()
|
||||
fn get_path_string(dir_entry: io::Result<fs::DirEntry>) -> PathBuf {
|
||||
dir_entry.expect("Couldn't get DirEntry").path().to_owned()
|
||||
}
|
||||
|
||||
// Integration tests. The files in the tests/source are formatted and compared
|
||||
@ -68,12 +68,12 @@ fn coverage_tests() {
|
||||
fn checkstyle_test() {
|
||||
let filename = "tests/writemode/source/fn-single-line.rs";
|
||||
let expected_filename = "tests/writemode/target/checkstyle.xml";
|
||||
assert_output(filename, expected_filename);
|
||||
assert_output(Path::new(filename), Path::new(expected_filename));
|
||||
}
|
||||
|
||||
// Helper function for comparing the results of rustfmt
|
||||
// to a known output file generated by one of the write modes.
|
||||
fn assert_output(source: &str, expected_filename: &str) {
|
||||
fn assert_output(source: &Path, expected_filename: &Path) {
|
||||
let config = read_config(source);
|
||||
let (file_map, _report) = format_file(source, &config);
|
||||
|
||||
@ -91,7 +91,7 @@ fn assert_output(source: &str, expected_filename: &str) {
|
||||
let compare = make_diff(&expected_text, &output, DIFF_CONTEXT_SIZE);
|
||||
if !compare.is_empty() {
|
||||
let mut failures = HashMap::new();
|
||||
failures.insert(source.to_string(), compare);
|
||||
failures.insert(source.to_owned(), compare);
|
||||
print_mismatches(failures);
|
||||
assert!(false, "Text does not match expected output");
|
||||
}
|
||||
@ -121,8 +121,8 @@ fn self_tests() {
|
||||
.chain(fs::read_dir("tests").expect("Couldn't read tests dir"))
|
||||
.map(get_path_string);
|
||||
// Hack because there's no `IntoIterator` impl for `[T; N]`.
|
||||
let files = files.chain(Some("src/lib.rs".to_owned()).into_iter());
|
||||
let files = files.chain(Some("build.rs".to_owned()).into_iter());
|
||||
let files = files.chain(Some(PathBuf::from("src/lib.rs")).into_iter());
|
||||
let files = files.chain(Some(PathBuf::from("build.rs")).into_iter());
|
||||
|
||||
let (reports, count, fails) = check_files(files);
|
||||
let mut warnings = 0;
|
||||
@ -152,9 +152,11 @@ fn stdin_formatting_smoke_test() {
|
||||
format_input::<io::Stdout>(input, &config, None).unwrap();
|
||||
assert!(error_summary.has_no_errors());
|
||||
for &(ref file_name, ref text) in &file_map {
|
||||
if file_name == "stdin" {
|
||||
assert_eq!(text.to_string(), "fn main() {}\n");
|
||||
return;
|
||||
if let FileName::Custom(ref file_name) = *file_name {
|
||||
if file_name == "stdin" {
|
||||
assert_eq!(text.to_string(), "fn main() {}\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
panic!("no stdin");
|
||||
@ -197,14 +199,14 @@ fn format_lines_errors_are_reported() {
|
||||
// Returns the number of files checked and the number of failures.
|
||||
fn check_files<I>(files: I) -> (Vec<FormatReport>, u32, u32)
|
||||
where
|
||||
I: Iterator<Item = String>,
|
||||
I: Iterator<Item = PathBuf>,
|
||||
{
|
||||
let mut count = 0;
|
||||
let mut fails = 0;
|
||||
let mut reports = vec![];
|
||||
|
||||
for file_name in files.filter(|f| f.ends_with(".rs")) {
|
||||
debug!("Testing '{}'...", file_name);
|
||||
for file_name in files.filter(|f| f.extension().map_or(false, |f| f == "rs")) {
|
||||
debug!("Testing '{}'...", file_name.display());
|
||||
|
||||
match idempotent_check(file_name) {
|
||||
Ok(ref report) if report.has_warnings() => {
|
||||
@ -224,13 +226,13 @@ where
|
||||
(reports, count, fails)
|
||||
}
|
||||
|
||||
fn print_mismatches(result: HashMap<String, Vec<Mismatch>>) {
|
||||
fn print_mismatches(result: HashMap<PathBuf, Vec<Mismatch>>) {
|
||||
let mut t = term::stdout().unwrap();
|
||||
|
||||
for (file_name, diff) in result {
|
||||
print_diff(
|
||||
diff,
|
||||
|line_num| format!("\nMismatch at {}:{}:", file_name, line_num),
|
||||
|line_num| format!("\nMismatch at {}:{}:", file_name.display(), line_num),
|
||||
Color::Auto,
|
||||
);
|
||||
}
|
||||
@ -238,20 +240,15 @@ fn print_mismatches(result: HashMap<String, Vec<Mismatch>>) {
|
||||
t.reset().unwrap();
|
||||
}
|
||||
|
||||
fn read_config(filename: &str) -> Config {
|
||||
fn read_config(filename: &Path) -> Config {
|
||||
let sig_comments = read_significant_comments(filename);
|
||||
// Look for a config file... If there is a 'config' property in the significant comments, use
|
||||
// that. Otherwise, if there are no significant comments at all, look for a config file with
|
||||
// the same name as the test file.
|
||||
let mut config = if !sig_comments.is_empty() {
|
||||
get_config(sig_comments.get("config").map(|x| &(*x)[..]))
|
||||
get_config(sig_comments.get("config").map(Path::new))
|
||||
} else {
|
||||
get_config(
|
||||
Path::new(filename)
|
||||
.with_extension("toml")
|
||||
.file_name()
|
||||
.and_then(std::ffi::OsStr::to_str),
|
||||
)
|
||||
get_config(filename.with_extension("toml").file_name().map(Path::new))
|
||||
};
|
||||
|
||||
for (key, val) in &sig_comments {
|
||||
@ -274,7 +271,9 @@ fn format_file<P: Into<PathBuf>>(filepath: P, config: &Config) -> (FileMap, Form
|
||||
(file_map, report)
|
||||
}
|
||||
|
||||
pub fn idempotent_check(filename: String) -> Result<FormatReport, HashMap<String, Vec<Mismatch>>> {
|
||||
pub fn idempotent_check(
|
||||
filename: PathBuf,
|
||||
) -> Result<FormatReport, HashMap<PathBuf, Vec<Mismatch>>> {
|
||||
let sig_comments = read_significant_comments(&filename);
|
||||
let config = read_config(&filename);
|
||||
let (file_map, format_report) = format_file(filename, &config);
|
||||
@ -286,7 +285,9 @@ pub fn idempotent_check(filename: String) -> Result<FormatReport, HashMap<String
|
||||
write_system_newlines(&mut v, text, &config).unwrap();
|
||||
// Won't panic, we are writing correct utf8.
|
||||
let one_result = String::from_utf8(v).unwrap();
|
||||
write_result.insert(filename.clone(), one_result);
|
||||
if let FileName::Real(ref filename) = *filename {
|
||||
write_result.insert(filename.to_owned(), one_result);
|
||||
}
|
||||
}
|
||||
|
||||
let target = sig_comments.get("target").map(|x| &(*x)[..]);
|
||||
@ -297,13 +298,13 @@ pub fn idempotent_check(filename: String) -> Result<FormatReport, HashMap<String
|
||||
// Reads test config file using the supplied (optional) file name. If there's no file name or the
|
||||
// file doesn't exist, just return the default config. Otherwise, the file must be read
|
||||
// successfully.
|
||||
fn get_config(config_file: Option<&str>) -> Config {
|
||||
fn get_config(config_file: Option<&Path>) -> Config {
|
||||
let config_file_name = match config_file {
|
||||
None => return Default::default(),
|
||||
Some(file_name) => {
|
||||
let mut full_path = "tests/config/".to_owned();
|
||||
full_path.push_str(file_name);
|
||||
if !Path::new(&full_path).exists() {
|
||||
let mut full_path = PathBuf::from("tests/config/");
|
||||
full_path.push(file_name);
|
||||
if !full_path.exists() {
|
||||
return Default::default();
|
||||
};
|
||||
full_path
|
||||
@ -321,8 +322,9 @@ fn get_config(config_file: Option<&str>) -> Config {
|
||||
|
||||
// Reads significant comments of the form: // rustfmt-key: value
|
||||
// into a hash map.
|
||||
fn read_significant_comments(file_name: &str) -> HashMap<String, String> {
|
||||
let file = fs::File::open(file_name).expect(&format!("Couldn't read file {}", file_name));
|
||||
fn read_significant_comments(file_name: &Path) -> HashMap<String, String> {
|
||||
let file =
|
||||
fs::File::open(file_name).expect(&format!("Couldn't read file {}", file_name.display()));
|
||||
let reader = BufReader::new(file);
|
||||
let pattern = r"^\s*//\s*rustfmt-([^:]+):\s*(\S+)";
|
||||
let regex = regex::Regex::new(pattern).expect("Failed creating pattern 1");
|
||||
@ -357,9 +359,9 @@ fn read_significant_comments(file_name: &str) -> HashMap<String, String> {
|
||||
// Compare output to input.
|
||||
// TODO: needs a better name, more explanation.
|
||||
fn handle_result(
|
||||
result: HashMap<String, String>,
|
||||
result: HashMap<PathBuf, String>,
|
||||
target: Option<&str>,
|
||||
) -> Result<(), HashMap<String, Vec<Mismatch>>> {
|
||||
) -> Result<(), HashMap<PathBuf, Vec<Mismatch>>> {
|
||||
let mut failures = HashMap::new();
|
||||
|
||||
for (file_name, fmt_text) in result {
|
||||
@ -391,15 +393,21 @@ fn handle_result(
|
||||
}
|
||||
|
||||
// Map source file paths to their target paths.
|
||||
fn get_target(file_name: &str, target: Option<&str>) -> String {
|
||||
if file_name.contains("source") {
|
||||
let target_file_name = file_name.replace("source", "target");
|
||||
fn get_target(file_name: &Path, target: Option<&str>) -> PathBuf {
|
||||
if let Some(n) = file_name
|
||||
.components()
|
||||
.position(|c| c.as_os_str() == "source")
|
||||
{
|
||||
let mut target_file_name = PathBuf::new();
|
||||
for (i, c) in file_name.components().enumerate() {
|
||||
if i == n {
|
||||
target_file_name.push("target");
|
||||
} else {
|
||||
target_file_name.push(c.as_os_str());
|
||||
}
|
||||
}
|
||||
if let Some(replace_name) = target {
|
||||
Path::new(&target_file_name)
|
||||
.with_file_name(replace_name)
|
||||
.into_os_string()
|
||||
.into_string()
|
||||
.unwrap()
|
||||
target_file_name.with_file_name(replace_name)
|
||||
} else {
|
||||
target_file_name
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user