Merge pull request #3522 from topecongiro/issue-3521

Add a path to the parent dir of rustfmt.toml as a prefix to paths in ignore
This commit is contained in:
Seiichi Uchida 2019-04-24 07:22:40 -07:00 committed by GitHub
commit aeb556ecb2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 73 additions and 31 deletions

View File

@ -141,7 +141,7 @@ macro_rules! create_config {
ConfigWasSet(self)
}
fn fill_from_parsed_config(mut self, parsed: PartialConfig) -> Config {
fn fill_from_parsed_config(mut self, parsed: PartialConfig, dir: &Path) -> Config {
$(
if let Some(val) = parsed.$i {
if self.$i.3 {
@ -160,6 +160,7 @@ macro_rules! create_config {
)+
self.set_heuristics();
self.set_license_template();
self.set_ignore(dir);
self
}
@ -286,6 +287,9 @@ macro_rules! create_config {
}
}
fn set_ignore(&mut self, dir: &Path) {
self.ignore.2.add_prefix(dir);
}
/// Returns `true` if the config key was explicitly set and is the default value.
pub fn is_default(&self, key: &str) -> bool {

View File

@ -190,7 +190,8 @@ impl Config {
let mut file = File::open(&file_path)?;
let mut toml = String::new();
file.read_to_string(&mut toml)?;
Config::from_toml(&toml).map_err(|err| Error::new(ErrorKind::InvalidData, err))
Config::from_toml(&toml, file_path.parent().unwrap())
.map_err(|err| Error::new(ErrorKind::InvalidData, err))
}
/// Resolves the config for input in `dir`.
@ -252,7 +253,7 @@ impl Config {
}
}
pub(crate) fn from_toml(toml: &str) -> Result<Config, String> {
pub(crate) fn from_toml(toml: &str, dir: &Path) -> Result<Config, String> {
let parsed: ::toml::Value = toml
.parse()
.map_err(|e| format!("Could not parse TOML: {}", e))?;
@ -271,7 +272,7 @@ impl Config {
if !err.is_empty() {
eprint!("{}", err);
}
Ok(Config::default().fill_from_parsed_config(parsed_config))
Ok(Config::default().fill_from_parsed_config(parsed_config, dir))
}
Err(e) => {
err.push_str("Error: Decoding config file failed:\n");
@ -425,7 +426,7 @@ mod test {
#[test]
fn test_was_set() {
let config = Config::from_toml("hard_tabs = true").unwrap();
let config = Config::from_toml("hard_tabs = true", Path::new("")).unwrap();
assert_eq!(config.was_set().hard_tabs(), true);
assert_eq!(config.was_set().verbose(), false);

View File

@ -1,7 +1,9 @@
use std::collections::{hash_set, HashSet};
use std::fmt;
use std::path::{Path, PathBuf};
use atty;
use serde::de::{Deserialize, Deserializer, SeqAccess, Visitor};
use crate::config::config_type::ConfigType;
use crate::config::lists::*;
@ -396,33 +398,63 @@ impl Default for EmitMode {
}
/// A set of directories, files and modules that rustfmt should ignore.
#[derive(Default, Deserialize, Serialize, Clone, Debug, PartialEq)]
pub struct IgnoreList(HashSet<PathBuf>);
#[derive(Default, Serialize, Clone, Debug, PartialEq)]
pub struct IgnoreList {
/// A set of path specified in rustfmt.toml.
#[serde(flatten)]
path_set: HashSet<PathBuf>,
/// A path to rustfmt.toml.
#[serde(skip_serializing)]
rustfmt_toml_path: PathBuf,
}
impl<'de> Deserialize<'de> for IgnoreList {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
struct HashSetVisitor;
impl<'v> Visitor<'v> for HashSetVisitor {
type Value = HashSet<PathBuf>;
fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
formatter.write_str("a sequence of path")
}
fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
where
A: SeqAccess<'v>,
{
let mut path_set = HashSet::new();
while let Some(elem) = seq.next_element()? {
path_set.insert(elem);
}
Ok(path_set)
}
}
Ok(IgnoreList {
path_set: deserializer.deserialize_seq(HashSetVisitor)?,
rustfmt_toml_path: PathBuf::new(),
})
}
}
impl<'a> IntoIterator for &'a IgnoreList {
type Item = &'a PathBuf;
type IntoIter = hash_set::Iter<'a, PathBuf>;
fn into_iter(self) -> Self::IntoIter {
self.0.iter()
self.path_set.iter()
}
}
impl IgnoreList {
pub fn add_prefix(&mut self, dir: &Path) {
self.0 = self
.0
.iter()
.map(|s| {
if s.has_root() {
s.clone()
} else {
let mut path = PathBuf::from(dir);
path.push(s);
path
}
})
.collect();
self.rustfmt_toml_path = dir.to_path_buf();
}
pub fn rustfmt_toml_path(&self) -> &Path {
&self.rustfmt_toml_path
}
}

View File

@ -67,6 +67,14 @@ fn format_project<T: FormatHandler>(
let main_file = input.file_name();
let input_is_stdin = main_file == FileName::Stdin;
let ignore_path_set = match IgnorePathSet::from_ignore_list(&config.ignore()) {
Ok(set) => set,
Err(e) => return Err(ErrorKind::InvalidGlobPattern(e)),
};
if config.skip_children() && ignore_path_set.is_match(&main_file) {
return Ok(FormatReport::new());
}
// Parse the crate.
let source_map = Rc::new(SourceMap::new(FilePathMapping::empty()));
let mut parse_session = make_parse_sess(source_map.clone(), config);
@ -91,11 +99,6 @@ fn format_project<T: FormatHandler>(
parse_session.span_diagnostic = Handler::with_emitter(true, None, silent_emitter);
let mut context = FormatContext::new(&krate, report, parse_session, config, handler);
let ignore_path_set = match IgnorePathSet::from_ignore_list(&config.ignore()) {
Ok(set) => set,
Err(e) => return Err(ErrorKind::InvalidGlobPattern(e)),
};
let files = modules::ModResolver::new(
context.parse_session.source_map(),
directory_ownership.unwrap_or(parse::DirectoryOwnership::UnownedViaMod(false)),

View File

@ -1,5 +1,4 @@
use ignore::{self, gitignore};
use std::path::PathBuf;
use crate::config::{FileName, IgnoreList};
@ -9,7 +8,7 @@ pub struct IgnorePathSet {
impl IgnorePathSet {
pub fn from_ignore_list(ignore_list: &IgnoreList) -> Result<Self, ignore::Error> {
let mut ignore_builder = gitignore::GitignoreBuilder::new(PathBuf::from(""));
let mut ignore_builder = gitignore::GitignoreBuilder::new(ignore_list.rustfmt_toml_path());
for ignore_path in ignore_list {
ignore_builder.add_line(None, ignore_path.to_str().unwrap())?;
@ -33,16 +32,19 @@ impl IgnorePathSet {
#[cfg(test)]
mod test {
use std::path::{Path, PathBuf};
use crate::config::{Config, FileName};
use crate::ignore_path::IgnorePathSet;
use std::path::PathBuf;
#[test]
fn test_ignore_path_set() {
match option_env!("CFG_RELEASE_CHANNEL") {
// this test requires nightly
None | Some("nightly") => {
let config = Config::from_toml(r#"ignore = ["foo.rs", "bar_dir/*"]"#).unwrap();
let config =
Config::from_toml(r#"ignore = ["foo.rs", "bar_dir/*"]"#, Path::new(""))
.unwrap();
let ignore_path_set = IgnorePathSet::from_ignore_list(&config.ignore()).unwrap();
assert!(ignore_path_set.is_match(&FileName::Real(PathBuf::from("src/foo.rs"))));

View File

@ -564,7 +564,7 @@ fn get_config(config_file: Option<&Path>) -> Config {
.read_to_string(&mut def_config)
.expect("Couldn't read config");
Config::from_toml(&def_config).expect("invalid TOML")
Config::from_toml(&def_config, Path::new("tests/config/")).expect("invalid TOML")
}
// Reads significant comments of the form: `// rustfmt-key: value` into a hash map.