Skip to content

Commit 3b60f3e

Browse files
committed
[feat] implement wildcard macro invocation skip
1 parent 342925a commit 3b60f3e

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
@@ -1019,33 +1019,47 @@ See also [`format_macro_matchers`](#format_macro_matchers).
10191019
Skip formatting the bodies of macro invocations with the following names.
10201020

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

10251025
#### `[]` (default):
10261026

1027-
The input:
1027+
All macro invocations will be formatted.
10281028

10291029
```rust
1030-
items!(
1031-
const _: u8 = 0;
1030+
lorem!(
1031+
const _: u8 = 0;
1032+
);
1033+
1034+
ipsum!(
1035+
const _: u8 = 0;
10321036
);
10331037
```
10341038

1035-
Is reformatted to:
1039+
#### `["lorem"]`:
1040+
1041+
The named macro invocations will be skipped.
10361042

10371043
```rust
1038-
items!(
1044+
lorem!(
1045+
const _: u8 = 0;
1046+
);
1047+
1048+
ipsum!(
10391049
const _: u8 = 0;
10401050
);
10411051
```
10421052

1043-
#### `["items"]`:
1053+
#### `["*"]`:
10441054

1045-
The input is preserved:
1055+
The special selector `*` will skip all macro invocations.
10461056

10471057
```rust
1048-
items!(
1058+
lorem!(
1059+
const _: u8 = 0;
1060+
);
1061+
1062+
ipsum!(
10491063
const _: u8 = 0;
10501064
);
10511065
```

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`.
@@ -47,7 +47,7 @@ impl ConfigType for FileLines {
4747
}
4848
}
4949

50-
impl ConfigType for MacroNames {
50+
impl ConfigType for MacroSelectors {
5151
fn doc_hint() -> String {
5252
String::from("[<string>, ...]")
5353
}

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
@@ -13,7 +13,7 @@ pub use crate::config::file_lines::{FileLines, FileName, Range};
1313
#[allow(unreachable_pub)]
1414
pub use crate::config::lists::*;
1515
#[allow(unreachable_pub)]
16-
pub use crate::config::macro_names::MacroNames;
16+
pub use crate::config::macro_names::{MacroSelector, MacroSelectors};
1717
#[allow(unreachable_pub)]
1818
pub use crate::config::options::*;
1919

@@ -70,7 +70,7 @@ create_config! {
7070
format_macro_matchers: bool, false, false,
7171
"Format the metavariable matching patterns in macros";
7272
format_macro_bodies: bool, true, false, "Format the bodies of macros";
73-
skip_macro_names: MacroNames, MacroNames::default(), false,
73+
skip_macro_names: MacroSelectors, MacroSelectors::default(), false,
7474
"Skip formatting the bodies of macros invoked with the following names.";
7575
hex_literal_case: HexLiteralCase, HexLiteralCase::Preserve, false,
7676
"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,
@@ -771,7 +771,14 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
771771
report: FormatReport,
772772
) -> FmtVisitor<'a> {
773773
let mut skip_context = SkipContext::default();
774-
skip_context.update_macros(config.skip_macro_names().into_name_strings());
774+
let mut macro_names = Vec::new();
775+
for macro_selector in config.skip_macro_names().into_inner() {
776+
match macro_selector {
777+
MacroSelector::Name(name) => macro_names.push(name.to_string()),
778+
MacroSelector::All => skip_context.all_macros = true,
779+
}
780+
}
781+
skip_context.update_macros(macro_names);
775782
FmtVisitor {
776783
parent_context: None,
777784
parse_sess: parse_session,

0 commit comments

Comments
 (0)