Skip to content

Commit a0e063a

Browse files
authored
Merge pull request #2522 from topecongiro/ignore-config-option
Add ignore config option
2 parents 047a520 + 3999d64 commit a0e063a

File tree

7 files changed

+104
-11
lines changed

7 files changed

+104
-11
lines changed

Configurations.md

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2135,3 +2135,30 @@ Copyright 2018 The Rust Project Developers.`, etc.:
21352135
```
21362136

21372137
`\{`, `\}` and `\\` match literal braces / backslashes.
2138+
2139+
## `ignore`
2140+
2141+
Skip formatting the specified files and directories.
2142+
2143+
- **Default value**: format every files
2144+
- **Possible values**: See an example below
2145+
- **Stable**: No
2146+
2147+
### Example
2148+
2149+
If you want to ignore specific files, put the following to your config file:
2150+
2151+
```toml
2152+
ignore = [
2153+
"src/types.rs",
2154+
"src/foo/bar.rs",
2155+
]
2156+
```
2157+
2158+
If you want to ignore every file under `examples/`, put the following to your config file:
2159+
2160+
```toml
2161+
ignore [
2162+
"examples",
2163+
]
2164+
```

src/bin/main.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,14 @@ use std::{env, error};
1818
use std::fs::File;
1919
use std::io::{self, Read, Write};
2020
use std::path::{Path, PathBuf};
21+
use std::str::FromStr;
2122

2223
use getopts::{Matches, Options};
2324

2425
use rustfmt::config::{get_toml_path, Color, Config, WriteMode};
2526
use rustfmt::config::file_lines::FileLines;
2627
use rustfmt::{run, FileName, Input, Summary};
2728

28-
use std::str::FromStr;
29-
3029
type FmtError = Box<error::Error + Send + Sync>;
3130
type FmtResult<T> = std::result::Result<T, FmtError>;
3231

src/config/config_type.rs

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
// except according to those terms.
1010

1111
use config::file_lines::FileLines;
12-
use config::options::WidthHeuristics;
12+
use config::options::{IgnoreList, WidthHeuristics};
1313

1414
/// Trait for types that can be used in `Config`.
1515
pub trait ConfigType: Sized {
@@ -54,6 +54,12 @@ impl ConfigType for WidthHeuristics {
5454
}
5555
}
5656

57+
impl ConfigType for IgnoreList {
58+
fn doc_hint() -> String {
59+
String::from("[<string>,..]")
60+
}
61+
}
62+
5763
/// Check if we're in a nightly build.
5864
///
5965
/// The environment variable `CFG_RELEASE_CHANNEL` is set during the rustc bootstrap
@@ -176,7 +182,7 @@ macro_rules! create_config {
176182
ConfigWasSet(self)
177183
}
178184

179-
fn fill_from_parsed_config(mut self, parsed: PartialConfig) -> Config {
185+
fn fill_from_parsed_config(mut self, parsed: PartialConfig, dir: &Path) -> Config {
180186
$(
181187
if let Some(val) = parsed.$i {
182188
if self.$i.3 {
@@ -195,6 +201,7 @@ macro_rules! create_config {
195201
)+
196202
self.set_heuristics();
197203
self.set_license_template();
204+
self.set_ignore(dir);
198205
self
199206
}
200207

@@ -216,7 +223,7 @@ macro_rules! create_config {
216223
}
217224
}
218225

219-
pub fn from_toml(toml: &str) -> Result<Config, String> {
226+
pub fn from_toml(toml: &str, dir: &Path) -> Result<Config, String> {
220227
let parsed: ::toml::Value =
221228
toml.parse().map_err(|e| format!("Could not parse TOML: {}", e))?;
222229
let mut err: String = String::new();
@@ -236,7 +243,7 @@ macro_rules! create_config {
236243
if !err.is_empty() {
237244
eprint!("{}", err);
238245
}
239-
Ok(Config::default().fill_from_parsed_config(parsed_config))
246+
Ok(Config::default().fill_from_parsed_config(parsed_config, dir: &Path))
240247
}
241248
Err(e) => {
242249
err.push_str("Error: Decoding config file failed:\n");
@@ -300,7 +307,8 @@ macro_rules! create_config {
300307
let mut file = File::open(&file_path)?;
301308
let mut toml = String::new();
302309
file.read_to_string(&mut toml)?;
303-
Config::from_toml(&toml).map_err(|err| Error::new(ErrorKind::InvalidData, err))
310+
Config::from_toml(&toml, file_path.parent().unwrap())
311+
.map_err(|err| Error::new(ErrorKind::InvalidData, err))
304312
}
305313

306314
/// Resolve the config for input in `dir`.
@@ -401,6 +409,10 @@ macro_rules! create_config {
401409
}
402410
}
403411
}
412+
413+
fn set_ignore(&mut self, dir: &Path) {
414+
self.ignore.2.add_prefix(dir);
415+
}
404416
}
405417

406418
// Template for the default configuration

src/config/mod.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,8 @@ create_config! {
141141
"Report all, none or unnumbered occurrences of TODO in source file comments";
142142
report_fixme: ReportTactic, ReportTactic::Never, false,
143143
"Report all, none or unnumbered occurrences of FIXME in source file comments";
144+
ignore: IgnoreList, IgnoreList::default(), false,
145+
"Skip formatting the specified files and directories.";
144146

145147
// Not user-facing.
146148
verbose: bool, false, false, "Use verbose output";
@@ -208,7 +210,8 @@ mod test {
208210

209211
#[test]
210212
fn test_was_set() {
211-
let config = Config::from_toml("hard_tabs = true").unwrap();
213+
use std::path::Path;
214+
let config = Config::from_toml("hard_tabs = true", Path::new("")).unwrap();
212215

213216
assert_eq!(config.was_set().hard_tabs(), true);
214217
assert_eq!(config.was_set().verbose(), false);

src/config/options.rs

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,14 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11+
use syntax::codemap::FileName;
12+
1113
use config::config_type::ConfigType;
1214
use config::lists::*;
1315

16+
use std::collections::HashSet;
17+
use std::path::{Path, PathBuf};
18+
1419
/// Macro for deriving implementations of Serialize/Deserialize for enums
1520
#[macro_export]
1621
macro_rules! impl_enum_serialize_and_deserialize {
@@ -244,3 +249,50 @@ impl ::std::str::FromStr for WidthHeuristics {
244249
Err("WidthHeuristics is not parsable")
245250
}
246251
}
252+
253+
/// A set of directories, files and modules that rustfmt should ignore.
254+
#[derive(Default, Deserialize, Serialize, Clone, Debug)]
255+
pub struct IgnoreList(HashSet<PathBuf>);
256+
257+
impl IgnoreList {
258+
pub fn add_prefix(&mut self, dir: &Path) {
259+
self.0 = self.0
260+
.iter()
261+
.map(|s| {
262+
if s.has_root() {
263+
s.clone()
264+
} else {
265+
let mut path = PathBuf::from(dir);
266+
path.push(s);
267+
path
268+
}
269+
})
270+
.collect();
271+
}
272+
273+
fn skip_file_inner(&self, file: &Path) -> bool {
274+
for path in &self.0 {
275+
if file.starts_with(path) {
276+
return true;
277+
}
278+
}
279+
280+
false
281+
}
282+
283+
pub fn skip_file(&self, file: &FileName) -> bool {
284+
if let FileName::Real(ref path) = file {
285+
self.skip_file_inner(path)
286+
} else {
287+
false
288+
}
289+
}
290+
}
291+
292+
impl ::std::str::FromStr for IgnoreList {
293+
type Err = &'static str;
294+
295+
fn from_str(_: &str) -> Result<Self, Self::Err> {
296+
Err("IgnoreList is not parsable")
297+
}
298+
}

src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -341,7 +341,7 @@ where
341341
// nothing to distinguish the nested module contents.
342342
let skip_children = config.skip_children() || config.write_mode() == config::WriteMode::Plain;
343343
for (path, module) in modules::list_files(krate, parse_session.codemap())? {
344-
if skip_children && path != *main_file {
344+
if (skip_children && path != *main_file) || config.ignore().skip_file(&path) {
345345
continue;
346346
}
347347
should_emit_verbose(&path, config, || println!("Formatting {}", path));

tests/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -293,7 +293,7 @@ fn format_lines_errors_are_reported() {
293293
fn format_lines_errors_are_reported_with_tabs() {
294294
let long_identifier = String::from_utf8(vec![b'a'; 97]).unwrap();
295295
let input = Input::Text(format!("fn a() {{\n\t{}\n}}", long_identifier));
296-
let config = Config::from_toml("hard_tabs = true").unwrap();
296+
let config = Config::from_toml("hard_tabs = true", Path::new("")).unwrap();
297297
let (error_summary, _file_map, _report) =
298298
format_input::<io::Stdout>(input, &config, None).unwrap();
299299
assert!(error_summary.has_formatting_errors());
@@ -435,7 +435,7 @@ fn get_config(config_file: Option<&Path>) -> Config {
435435
.read_to_string(&mut def_config)
436436
.expect("Couldn't read config");
437437

438-
Config::from_toml(&def_config).expect("Invalid toml")
438+
Config::from_toml(&def_config, Path::new("tests/config/")).expect("Invalid toml")
439439
}
440440

441441
// Reads significant comments of the form: // rustfmt-key: value

0 commit comments

Comments
 (0)