Skip to content

Commit aeb556e

Browse files
authored
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
2 parents 05547d9 + f520f7e commit aeb556e

File tree

6 files changed

+73
-31
lines changed

6 files changed

+73
-31
lines changed

Diff for: src/config/config_type.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ macro_rules! create_config {
141141
ConfigWasSet(self)
142142
}
143143

144-
fn fill_from_parsed_config(mut self, parsed: PartialConfig) -> Config {
144+
fn fill_from_parsed_config(mut self, parsed: PartialConfig, dir: &Path) -> Config {
145145
$(
146146
if let Some(val) = parsed.$i {
147147
if self.$i.3 {
@@ -160,6 +160,7 @@ macro_rules! create_config {
160160
)+
161161
self.set_heuristics();
162162
self.set_license_template();
163+
self.set_ignore(dir);
163164
self
164165
}
165166

@@ -286,6 +287,9 @@ macro_rules! create_config {
286287
}
287288
}
288289

290+
fn set_ignore(&mut self, dir: &Path) {
291+
self.ignore.2.add_prefix(dir);
292+
}
289293

290294
/// Returns `true` if the config key was explicitly set and is the default value.
291295
pub fn is_default(&self, key: &str) -> bool {

Diff for: src/config/mod.rs

+5-4
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,8 @@ impl Config {
190190
let mut file = File::open(&file_path)?;
191191
let mut toml = String::new();
192192
file.read_to_string(&mut toml)?;
193-
Config::from_toml(&toml).map_err(|err| Error::new(ErrorKind::InvalidData, err))
193+
Config::from_toml(&toml, file_path.parent().unwrap())
194+
.map_err(|err| Error::new(ErrorKind::InvalidData, err))
194195
}
195196

196197
/// Resolves the config for input in `dir`.
@@ -252,7 +253,7 @@ impl Config {
252253
}
253254
}
254255

255-
pub(crate) fn from_toml(toml: &str) -> Result<Config, String> {
256+
pub(crate) fn from_toml(toml: &str, dir: &Path) -> Result<Config, String> {
256257
let parsed: ::toml::Value = toml
257258
.parse()
258259
.map_err(|e| format!("Could not parse TOML: {}", e))?;
@@ -271,7 +272,7 @@ impl Config {
271272
if !err.is_empty() {
272273
eprint!("{}", err);
273274
}
274-
Ok(Config::default().fill_from_parsed_config(parsed_config))
275+
Ok(Config::default().fill_from_parsed_config(parsed_config, dir))
275276
}
276277
Err(e) => {
277278
err.push_str("Error: Decoding config file failed:\n");
@@ -425,7 +426,7 @@ mod test {
425426

426427
#[test]
427428
fn test_was_set() {
428-
let config = Config::from_toml("hard_tabs = true").unwrap();
429+
let config = Config::from_toml("hard_tabs = true", Path::new("")).unwrap();
429430

430431
assert_eq!(config.was_set().hard_tabs(), true);
431432
assert_eq!(config.was_set().verbose(), false);

Diff for: src/config/options.rs

+48-16
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
use std::collections::{hash_set, HashSet};
2+
use std::fmt;
23
use std::path::{Path, PathBuf};
34

45
use atty;
6+
use serde::de::{Deserialize, Deserializer, SeqAccess, Visitor};
57

68
use crate::config::config_type::ConfigType;
79
use crate::config::lists::*;
@@ -396,33 +398,63 @@ impl Default for EmitMode {
396398
}
397399

398400
/// A set of directories, files and modules that rustfmt should ignore.
399-
#[derive(Default, Deserialize, Serialize, Clone, Debug, PartialEq)]
400-
pub struct IgnoreList(HashSet<PathBuf>);
401+
#[derive(Default, Serialize, Clone, Debug, PartialEq)]
402+
pub struct IgnoreList {
403+
/// A set of path specified in rustfmt.toml.
404+
#[serde(flatten)]
405+
path_set: HashSet<PathBuf>,
406+
/// A path to rustfmt.toml.
407+
#[serde(skip_serializing)]
408+
rustfmt_toml_path: PathBuf,
409+
}
410+
411+
impl<'de> Deserialize<'de> for IgnoreList {
412+
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
413+
where
414+
D: Deserializer<'de>,
415+
{
416+
struct HashSetVisitor;
417+
impl<'v> Visitor<'v> for HashSetVisitor {
418+
type Value = HashSet<PathBuf>;
419+
420+
fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
421+
formatter.write_str("a sequence of path")
422+
}
423+
424+
fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
425+
where
426+
A: SeqAccess<'v>,
427+
{
428+
let mut path_set = HashSet::new();
429+
while let Some(elem) = seq.next_element()? {
430+
path_set.insert(elem);
431+
}
432+
Ok(path_set)
433+
}
434+
}
435+
Ok(IgnoreList {
436+
path_set: deserializer.deserialize_seq(HashSetVisitor)?,
437+
rustfmt_toml_path: PathBuf::new(),
438+
})
439+
}
440+
}
401441

402442
impl<'a> IntoIterator for &'a IgnoreList {
403443
type Item = &'a PathBuf;
404444
type IntoIter = hash_set::Iter<'a, PathBuf>;
405445

406446
fn into_iter(self) -> Self::IntoIter {
407-
self.0.iter()
447+
self.path_set.iter()
408448
}
409449
}
410450

411451
impl IgnoreList {
412452
pub fn add_prefix(&mut self, dir: &Path) {
413-
self.0 = self
414-
.0
415-
.iter()
416-
.map(|s| {
417-
if s.has_root() {
418-
s.clone()
419-
} else {
420-
let mut path = PathBuf::from(dir);
421-
path.push(s);
422-
path
423-
}
424-
})
425-
.collect();
453+
self.rustfmt_toml_path = dir.to_path_buf();
454+
}
455+
456+
pub fn rustfmt_toml_path(&self) -> &Path {
457+
&self.rustfmt_toml_path
426458
}
427459
}
428460

Diff for: src/formatting.rs

+8-5
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,14 @@ fn format_project<T: FormatHandler>(
6767
let main_file = input.file_name();
6868
let input_is_stdin = main_file == FileName::Stdin;
6969

70+
let ignore_path_set = match IgnorePathSet::from_ignore_list(&config.ignore()) {
71+
Ok(set) => set,
72+
Err(e) => return Err(ErrorKind::InvalidGlobPattern(e)),
73+
};
74+
if config.skip_children() && ignore_path_set.is_match(&main_file) {
75+
return Ok(FormatReport::new());
76+
}
77+
7078
// Parse the crate.
7179
let source_map = Rc::new(SourceMap::new(FilePathMapping::empty()));
7280
let mut parse_session = make_parse_sess(source_map.clone(), config);
@@ -91,11 +99,6 @@ fn format_project<T: FormatHandler>(
9199
parse_session.span_diagnostic = Handler::with_emitter(true, None, silent_emitter);
92100

93101
let mut context = FormatContext::new(&krate, report, parse_session, config, handler);
94-
let ignore_path_set = match IgnorePathSet::from_ignore_list(&config.ignore()) {
95-
Ok(set) => set,
96-
Err(e) => return Err(ErrorKind::InvalidGlobPattern(e)),
97-
};
98-
99102
let files = modules::ModResolver::new(
100103
context.parse_session.source_map(),
101104
directory_ownership.unwrap_or(parse::DirectoryOwnership::UnownedViaMod(false)),

Diff for: src/ignore_path.rs

+6-4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
use ignore::{self, gitignore};
2-
use std::path::PathBuf;
32

43
use crate::config::{FileName, IgnoreList};
54

@@ -9,7 +8,7 @@ pub struct IgnorePathSet {
98

109
impl IgnorePathSet {
1110
pub fn from_ignore_list(ignore_list: &IgnoreList) -> Result<Self, ignore::Error> {
12-
let mut ignore_builder = gitignore::GitignoreBuilder::new(PathBuf::from(""));
11+
let mut ignore_builder = gitignore::GitignoreBuilder::new(ignore_list.rustfmt_toml_path());
1312

1413
for ignore_path in ignore_list {
1514
ignore_builder.add_line(None, ignore_path.to_str().unwrap())?;
@@ -33,16 +32,19 @@ impl IgnorePathSet {
3332

3433
#[cfg(test)]
3534
mod test {
35+
use std::path::{Path, PathBuf};
36+
3637
use crate::config::{Config, FileName};
3738
use crate::ignore_path::IgnorePathSet;
38-
use std::path::PathBuf;
3939

4040
#[test]
4141
fn test_ignore_path_set() {
4242
match option_env!("CFG_RELEASE_CHANNEL") {
4343
// this test requires nightly
4444
None | Some("nightly") => {
45-
let config = Config::from_toml(r#"ignore = ["foo.rs", "bar_dir/*"]"#).unwrap();
45+
let config =
46+
Config::from_toml(r#"ignore = ["foo.rs", "bar_dir/*"]"#, Path::new(""))
47+
.unwrap();
4648
let ignore_path_set = IgnorePathSet::from_ignore_list(&config.ignore()).unwrap();
4749

4850
assert!(ignore_path_set.is_match(&FileName::Real(PathBuf::from("src/foo.rs"))));

Diff for: src/test/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -564,7 +564,7 @@ fn get_config(config_file: Option<&Path>) -> Config {
564564
.read_to_string(&mut def_config)
565565
.expect("Couldn't read config");
566566

567-
Config::from_toml(&def_config).expect("invalid TOML")
567+
Config::from_toml(&def_config, Path::new("tests/config/")).expect("invalid TOML")
568568
}
569569

570570
// Reads significant comments of the form: `// rustfmt-key: value` into a hash map.

0 commit comments

Comments
 (0)