Skip to content

Commit 2b455d1

Browse files
committed
[feat] implement wildcard macro invocation skip
1 parent 3021961 commit 2b455d1

File tree

7 files changed

+102
-38
lines changed

7 files changed

+102
-38
lines changed

Configurations.md

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1011,33 +1011,47 @@ See also [`format_macro_matchers`](#format_macro_matchers).
10111011
Skip formatting the bodies of macro invocations with the following names.
10121012

10131013
- **Default value**: `[]`
1014-
- **Possible values**: a list of macro name idents, `["name_0", "name_1", ...]`
1014+
- **Possible values**: a list of macro name idents, `["name_0", "name_1", ..., "*"]`
10151015
- **Stable**: No (tracking issue: [#5346](https://github.com/rust-lang/rustfmt/issues/5346))
10161016

10171017
#### `[]` (default):
10181018

1019-
The input:
1019+
All macro invocations will be formatted.
10201020

10211021
```rust
1022-
items!(
1023-
const _: u8 = 0;
1022+
lorem!(
1023+
const _: u8 = 0;
1024+
);
1025+
1026+
ipsum!(
1027+
const _: u8 = 0;
10241028
);
10251029
```
10261030

1027-
Is reformatted to:
1031+
#### `["lorem"]`:
1032+
1033+
The named macro invocations will be skipped.
10281034

10291035
```rust
1030-
items!(
1036+
lorem!(
1037+
const _: u8 = 0;
1038+
);
1039+
1040+
ipsum!(
10311041
const _: u8 = 0;
10321042
);
10331043
```
10341044

1035-
#### `["items"]`:
1045+
#### `["*"]`:
10361046

1037-
The input is preserved:
1047+
The special selector `*` will skip all macro invocations.
10381048

10391049
```rust
1040-
items!(
1050+
lorem!(
1051+
const _: u8 = 0;
1052+
);
1053+
1054+
ipsum!(
10411055
const _: u8 = 0;
10421056
);
10431057
```

src/config/config_type.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use crate::config::file_lines::FileLines;
2-
use crate::config::macro_names::MacroNames;
2+
use crate::config::macro_names::MacroSelectors;
33
use crate::config::options::{IgnoreList, WidthHeuristics};
44

55
/// Trait for types that can be used in `Config`.
@@ -39,7 +39,7 @@ impl ConfigType for FileLines {
3939
}
4040
}
4141

42-
impl ConfigType for MacroNames {
42+
impl ConfigType for MacroSelectors {
4343
fn doc_hint() -> String {
4444
String::from("[<string>, ...]")
4545
}

src/config/macro_names.rs

Lines changed: 58 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -23,35 +23,68 @@ impl From<MacroName> for String {
2323
}
2424
}
2525

26-
/// A set of macro names.
27-
#[derive(Clone, Debug, Default, PartialEq, Deserialize, Serialize)]
28-
pub struct MacroNames(Vec<MacroName>);
26+
/// Defines a selector to match against a macro.
27+
#[derive(Clone, Debug, Eq, PartialEq, Hash, Ord, PartialOrd, Deserialize, Serialize)]
28+
pub enum MacroSelector {
29+
Name(MacroName),
30+
All,
31+
}
2932

30-
impl fmt::Display for MacroNames {
33+
impl fmt::Display for MacroSelector {
3134
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
32-
write!(f, "{}", self.0.iter().format(", "))
35+
match self {
36+
Self::Name(name) => name.fmt(f),
37+
Self::All => write!(f, "*"),
38+
}
39+
}
40+
}
41+
42+
impl str::FromStr for MacroSelector {
43+
type Err = std::convert::Infallible;
44+
45+
fn from_str(s: &str) -> Result<Self, Self::Err> {
46+
Ok(match s {
47+
"*" => MacroSelector::All,
48+
name => MacroSelector::Name(MacroName(name.to_owned())),
49+
})
3350
}
3451
}
3552

36-
impl MacroNames {
37-
/// Return the underlying macro names, as an iterator of strings.
38-
pub(crate) fn into_name_strings(self) -> impl Iterator<Item = String> {
39-
self.0.into_iter().map(Into::into)
53+
/// A set of macro selectors.
54+
#[derive(Clone, Debug, Default, PartialEq, Deserialize, Serialize)]
55+
pub struct MacroSelectors(Vec<MacroSelector>);
56+
57+
impl MacroSelectors {
58+
pub fn into_inner(self) -> Vec<MacroSelector> {
59+
self.0
60+
}
61+
}
62+
63+
impl fmt::Display for MacroSelectors {
64+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
65+
write!(f, "{}", self.0.iter().format(", "))
4066
}
4167
}
4268

4369
#[derive(Error, Debug)]
44-
pub enum MacroNamesError {
70+
pub enum MacroSelectorsError {
4571
#[error("{0}")]
4672
Json(json::Error),
4773
}
4874

4975
// This impl is needed for `Config::override_value` to work for use in tests.
50-
impl str::FromStr for MacroNames {
51-
type Err = MacroNamesError;
76+
impl str::FromStr for MacroSelectors {
77+
type Err = MacroSelectorsError;
5278

53-
fn from_str(s: &str) -> Result<MacroNames, Self::Err> {
54-
json::from_str(s).map_err(MacroNamesError::Json)
79+
fn from_str(s: &str) -> Result<Self, Self::Err> {
80+
let raw: Vec<&str> = json::from_str(s).map_err(MacroSelectorsError::Json)?;
81+
Ok(Self(
82+
raw.into_iter()
83+
.map(|raw| {
84+
MacroSelector::from_str(raw).expect("MacroSelector from_str is infallible")
85+
})
86+
.collect(),
87+
))
5588
}
5689
}
5790

@@ -62,20 +95,24 @@ mod test {
6295

6396
#[test]
6497
fn macro_names_from_str() {
65-
let macro_names = MacroNames::from_str(r#"["foo", "bar"]"#).unwrap();
98+
let macro_names = MacroSelectors::from_str(r#"["foo", "*", "bar"]"#).unwrap();
6699
assert_eq!(
67100
macro_names,
68-
MacroNames(
69-
[MacroName("foo".to_owned()), MacroName("bar".to_owned())]
70-
.into_iter()
71-
.collect()
101+
MacroSelectors(
102+
[
103+
MacroSelector::Name(MacroName("foo".to_owned())),
104+
MacroSelector::All,
105+
MacroSelector::Name(MacroName("bar".to_owned()))
106+
]
107+
.into_iter()
108+
.collect()
72109
)
73110
);
74111
}
75112

76113
#[test]
77114
fn macro_names_display() {
78-
let macro_names = MacroNames::from_str(r#"["foo", "bar"]"#).unwrap();
79-
assert_eq!(format!("{}", macro_names), "foo, bar");
115+
let macro_names = MacroSelectors::from_str(r#"["foo", "*", "bar"]"#).unwrap();
116+
assert_eq!(format!("{}", macro_names), "foo, *, bar");
80117
}
81118
}

src/config/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ pub use crate::config::file_lines::{FileLines, FileName, Range};
1414
#[allow(unreachable_pub)]
1515
pub use crate::config::lists::*;
1616
#[allow(unreachable_pub)]
17-
pub use crate::config::macro_names::MacroNames;
17+
pub use crate::config::macro_names::{MacroSelector, MacroSelectors};
1818
#[allow(unreachable_pub)]
1919
pub use crate::config::options::*;
2020

@@ -72,7 +72,7 @@ create_config! {
7272
format_macro_matchers: bool, false, false,
7373
"Format the metavariable matching patterns in macros";
7474
format_macro_bodies: bool, true, false, "Format the bodies of macros";
75-
skip_macro_names: MacroNames, MacroNames::default(), false,
75+
skip_macro_names: MacroSelectors, MacroSelectors::default(), false,
7676
"Skip formatting the bodies of macros invoked with the following names.";
7777
hex_literal_case: HexLiteralCase, HexLiteralCase::Preserve, false,
7878
"Format hexadecimal integer literals";

src/skip.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ use rustc_ast_pretty::pprust;
77
/// by other context. Query this context to know if you need skip a block.
88
#[derive(Default, Clone)]
99
pub(crate) struct SkipContext {
10+
pub(crate) all_macros: bool,
1011
macros: Vec<String>,
1112
attributes: Vec<String>,
1213
}
@@ -31,7 +32,7 @@ impl SkipContext {
3132
}
3233

3334
pub(crate) fn skip_macro(&self, name: &str) -> bool {
34-
self.macros.iter().any(|n| n == name)
35+
self.all_macros || self.macros.iter().any(|n| n == name)
3536
}
3637

3738
pub(crate) fn skip_attribute(&self, name: &str) -> bool {

src/test/configuration_snippet.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,13 @@ impl ConfigurationSection {
2727
lazy_static! {
2828
static ref CONFIG_NAME_REGEX: regex::Regex =
2929
regex::Regex::new(r"^## `([^`]+)`").expect("failed creating configuration pattern");
30+
// Configuration values, which will be passed to `from_str`:
31+
//
32+
// - must be prefixed with `####`
33+
// - must be wrapped in backticks
34+
// - may by wrapped in double quotes (which will be stripped)
3035
static ref CONFIG_VALUE_REGEX: regex::Regex =
31-
regex::Regex::new(r#"^#### `"?([^`"]+)"?`"#)
36+
regex::Regex::new(r#"^#### `"?([^`]+?)"?`"#)
3237
.expect("failed creating configuration value pattern");
3338
}
3439

src/visitor.rs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use rustc_span::{symbol, BytePos, Pos, Span};
88
use crate::attr::*;
99
use crate::comment::{contains_comment, rewrite_comment, CodeCharKind, CommentCodeSlices};
1010
use crate::config::Version;
11-
use crate::config::{BraceStyle, Config};
11+
use crate::config::{BraceStyle, Config, MacroSelector};
1212
use crate::coverage::transform_missing_snippet;
1313
use crate::items::{
1414
format_impl, format_trait, format_trait_alias, is_mod_decl, is_use_item, rewrite_extern_crate,
@@ -770,7 +770,14 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
770770
memoize: Memoize,
771771
) -> FmtVisitor<'a> {
772772
let mut skip_context = SkipContext::default();
773-
skip_context.update_macros(config.skip_macro_names().into_name_strings());
773+
let mut macro_names = Vec::new();
774+
for macro_selector in config.skip_macro_names().into_inner() {
775+
match macro_selector {
776+
MacroSelector::Name(name) => macro_names.push(name.to_string()),
777+
MacroSelector::All => skip_context.all_macros = true,
778+
}
779+
}
780+
skip_context.update_macros(macro_names);
774781
FmtVisitor {
775782
parent_context: None,
776783
parse_sess: parse_session,

0 commit comments

Comments
 (0)