Add config options for formatting macro matchers and bodies
Closes #2753
This commit is contained in:
parent
b27d544478
commit
79c5ee8b42
3 changed files with 108 additions and 15 deletions
|
|
@ -1006,6 +1006,76 @@ fn main() {
|
||||||
|
|
||||||
See also [`max_width`](#max_width).
|
See also [`max_width`](#max_width).
|
||||||
|
|
||||||
|
## `format_macro_matchers`
|
||||||
|
|
||||||
|
Format the metavariable matching patterns in macros.
|
||||||
|
|
||||||
|
- **Default value**: `false`
|
||||||
|
- **Possible values**: `true`, `false`
|
||||||
|
- **Stable**: No
|
||||||
|
|
||||||
|
#### `false` (default):
|
||||||
|
|
||||||
|
```rust
|
||||||
|
macro_rules! foo {
|
||||||
|
($a: ident : $b: ty) => {
|
||||||
|
$a(42): $b;
|
||||||
|
};
|
||||||
|
($a: ident $b: ident $c: ident) => {
|
||||||
|
$a = $b + $c;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### `true`:
|
||||||
|
|
||||||
|
```rust
|
||||||
|
macro_rules! foo {
|
||||||
|
($a:ident : $b:ty) => {
|
||||||
|
$a(42): $b;
|
||||||
|
};
|
||||||
|
($a:ident $b:ident $c:ident) => {
|
||||||
|
$a = $b + $c;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
See also [`format_macro_bodies`](#format_macro_bodies).
|
||||||
|
|
||||||
|
|
||||||
|
## `format_macro_bodies`
|
||||||
|
|
||||||
|
Format the bodies of macros.
|
||||||
|
|
||||||
|
- **Default value**: `true`
|
||||||
|
- **Possible values**: `true`, `false`
|
||||||
|
- **Stable**: No
|
||||||
|
|
||||||
|
#### `true` (default):
|
||||||
|
|
||||||
|
```rust
|
||||||
|
macro_rules! foo {
|
||||||
|
($a:ident : $b:ty) => {
|
||||||
|
$a(42): $b;
|
||||||
|
};
|
||||||
|
($a:ident $b:ident $c:ident) => {
|
||||||
|
$a = $b + $c;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### `false`:
|
||||||
|
|
||||||
|
```rust
|
||||||
|
macro_rules! foo {
|
||||||
|
($a:ident : $b:ty) => { $a(42): $b; };
|
||||||
|
($a:ident $b:ident $c:ident) => { $a=$b+$c; };
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
See also [`format_macro_matchers`](#format_macro_matchers).
|
||||||
|
|
||||||
|
|
||||||
## `hard_tabs`
|
## `hard_tabs`
|
||||||
|
|
||||||
Use tab characters for indentation, spaces for alignment
|
Use tab characters for indentation, spaces for alignment
|
||||||
|
|
|
||||||
|
|
@ -42,10 +42,10 @@ create_config! {
|
||||||
tab_spaces: usize, 4, true, "Number of spaces per tab";
|
tab_spaces: usize, 4, true, "Number of spaces per tab";
|
||||||
newline_style: NewlineStyle, NewlineStyle::Native, true, "Unix or Windows line endings";
|
newline_style: NewlineStyle, NewlineStyle::Native, true, "Unix or Windows line endings";
|
||||||
use_small_heuristics: Heuristics, Heuristics::Default, true, "Whether to use different \
|
use_small_heuristics: Heuristics, Heuristics::Default, true, "Whether to use different \
|
||||||
formatting for items and expressions if they satisfy a heuristic notion of 'small'.";
|
formatting for items and expressions if they satisfy a heuristic notion of 'small'";
|
||||||
indent_style: IndentStyle, IndentStyle::Block, false, "How do we indent expressions or items.";
|
indent_style: IndentStyle, IndentStyle::Block, false, "How do we indent expressions or items";
|
||||||
|
|
||||||
// Comments and strings
|
// Comments. macros, and strings
|
||||||
wrap_comments: bool, false, false, "Break comments to fit on the line";
|
wrap_comments: bool, false, false, "Break comments to fit on the line";
|
||||||
comment_width: usize, 80, false,
|
comment_width: usize, 80, false,
|
||||||
"Maximum length of comments. No effect unless wrap_comments = true";
|
"Maximum length of comments. No effect unless wrap_comments = true";
|
||||||
|
|
@ -53,6 +53,9 @@ create_config! {
|
||||||
license_template_path: String, String::default(), false,
|
license_template_path: String, String::default(), false,
|
||||||
"Beginning of file must match license template";
|
"Beginning of file must match license template";
|
||||||
format_strings: bool, false, false, "Format string literals where necessary";
|
format_strings: bool, false, false, "Format string literals where necessary";
|
||||||
|
format_macro_matchers: bool, true, false,
|
||||||
|
"Format the metavariable matching patterns in macros";
|
||||||
|
format_macro_bodies: bool, true, false, "Format the bodies of macros";
|
||||||
|
|
||||||
// Single line expressions and items
|
// Single line expressions and items
|
||||||
empty_item_single_line: bool, true, false,
|
empty_item_single_line: bool, true, false,
|
||||||
|
|
@ -79,13 +82,13 @@ create_config! {
|
||||||
space_after_colon: bool, true, false, "Leave a space after the colon";
|
space_after_colon: bool, true, false, "Leave a space after the colon";
|
||||||
spaces_around_ranges: bool, false, false, "Put spaces around the .. and ..= range operators";
|
spaces_around_ranges: bool, false, false, "Put spaces around the .. and ..= range operators";
|
||||||
binop_separator: SeparatorPlace, SeparatorPlace::Front, false,
|
binop_separator: SeparatorPlace, SeparatorPlace::Front, false,
|
||||||
"Where to put a binary operator when a binary expression goes multiline.";
|
"Where to put a binary operator when a binary expression goes multiline";
|
||||||
|
|
||||||
// Misc.
|
// Misc.
|
||||||
remove_nested_parens: bool, true, true, "Remove nested parens.";
|
remove_nested_parens: bool, true, true, "Remove nested parens";
|
||||||
combine_control_expr: bool, true, false, "Combine control expressions with function calls.";
|
combine_control_expr: bool, true, false, "Combine control expressions with function calls";
|
||||||
struct_field_align_threshold: usize, 0, false, "Align struct fields if their diffs fits within \
|
struct_field_align_threshold: usize, 0, false, "Align struct fields if their diffs fits within \
|
||||||
threshold.";
|
threshold";
|
||||||
match_arm_blocks: bool, true, false, "Wrap the body of arms in blocks when it does not fit on \
|
match_arm_blocks: bool, true, false, "Wrap the body of arms in blocks when it does not fit on \
|
||||||
the same line with the pattern of arms";
|
the same line with the pattern of arms";
|
||||||
force_multiline_blocks: bool, false, false,
|
force_multiline_blocks: bool, false, false,
|
||||||
|
|
@ -101,10 +104,10 @@ create_config! {
|
||||||
match_block_trailing_comma: bool, false, false,
|
match_block_trailing_comma: bool, false, false,
|
||||||
"Put a trailing comma after a block based match arm (non-block arms are not affected)";
|
"Put a trailing comma after a block based match arm (non-block arms are not affected)";
|
||||||
blank_lines_upper_bound: usize, 1, false,
|
blank_lines_upper_bound: usize, 1, false,
|
||||||
"Maximum number of blank lines which can be put between items.";
|
"Maximum number of blank lines which can be put between items";
|
||||||
blank_lines_lower_bound: usize, 0, false,
|
blank_lines_lower_bound: usize, 0, false,
|
||||||
"Minimum number of blank lines which must be put between items.";
|
"Minimum number of blank lines which must be put between items";
|
||||||
edition: Edition, Edition::Edition2015, false, "The edition of the parser. (RFC 2052)";
|
edition: Edition, Edition::Edition2015, false, "The edition of the parser (RFC 2052)";
|
||||||
|
|
||||||
// Options that can change the source code beyond whitespace/blocks (somewhat linty things)
|
// Options that can change the source code beyond whitespace/blocks (somewhat linty things)
|
||||||
merge_derives: bool, true, true, "Merge multiple `#[derive(...)]` into a single one";
|
merge_derives: bool, true, true, "Merge multiple `#[derive(...)]` into a single one";
|
||||||
|
|
@ -118,7 +121,7 @@ create_config! {
|
||||||
color: Color, Color::Auto, false,
|
color: Color, Color::Auto, false,
|
||||||
"What Color option to use when none is supplied: Always, Never, Auto";
|
"What Color option to use when none is supplied: Always, Never, Auto";
|
||||||
required_version: String, env!("CARGO_PKG_VERSION").to_owned(), false,
|
required_version: String, env!("CARGO_PKG_VERSION").to_owned(), false,
|
||||||
"Require a specific version of rustfmt.";
|
"Require a specific version of rustfmt";
|
||||||
unstable_features: bool, false, false,
|
unstable_features: bool, false, false,
|
||||||
"Enables unstable features. Only available on nightly channel";
|
"Enables unstable features. Only available on nightly channel";
|
||||||
disable_all_formatting: bool, false, false, "Don't reformat anything";
|
disable_all_formatting: bool, false, false, "Don't reformat anything";
|
||||||
|
|
@ -133,7 +136,7 @@ create_config! {
|
||||||
report_fixme: ReportTactic, ReportTactic::Never, false,
|
report_fixme: ReportTactic, ReportTactic::Never, false,
|
||||||
"Report all, none or unnumbered occurrences of FIXME in source file comments";
|
"Report all, none or unnumbered occurrences of FIXME in source file comments";
|
||||||
ignore: IgnoreList, IgnoreList::default(), false,
|
ignore: IgnoreList, IgnoreList::default(), false,
|
||||||
"Skip formatting the specified files and directories.";
|
"Skip formatting the specified files and directories";
|
||||||
|
|
||||||
// Not user-facing
|
// Not user-facing
|
||||||
verbose: Verbosity, Verbosity::Normal, false, "How much to information to emit to the user";
|
verbose: Verbosity, Verbosity::Normal, false, "How much to information to emit to the user";
|
||||||
|
|
|
||||||
|
|
@ -938,10 +938,22 @@ fn format_macro_args(
|
||||||
toks: ThinTokenStream,
|
toks: ThinTokenStream,
|
||||||
shape: Shape,
|
shape: Shape,
|
||||||
) -> Option<String> {
|
) -> Option<String> {
|
||||||
|
if !context.config.format_macro_matchers() {
|
||||||
|
let token_stream: TokenStream = toks.into();
|
||||||
|
let span = span_for_token_stream(token_stream);
|
||||||
|
return Some(match span {
|
||||||
|
Some(span) => context.snippet(span).to_owned(),
|
||||||
|
None => String::new(),
|
||||||
|
});
|
||||||
|
}
|
||||||
let parsed_args = MacroArgParser::new().parse(toks)?;
|
let parsed_args = MacroArgParser::new().parse(toks)?;
|
||||||
wrap_macro_args(context, &parsed_args, shape)
|
wrap_macro_args(context, &parsed_args, shape)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn span_for_token_stream(token_stream: TokenStream) -> Option<Span> {
|
||||||
|
token_stream.trees().next().map(|tt| tt.span())
|
||||||
|
}
|
||||||
|
|
||||||
// We should insert a space if the next token is a:
|
// We should insert a space if the next token is a:
|
||||||
#[derive(Copy, Clone, PartialEq)]
|
#[derive(Copy, Clone, PartialEq)]
|
||||||
enum SpaceState {
|
enum SpaceState {
|
||||||
|
|
@ -1172,13 +1184,14 @@ impl MacroParser {
|
||||||
TokenTree::Token(_, Token::FatArrow) => {}
|
TokenTree::Token(_, Token::FatArrow) => {}
|
||||||
_ => return None,
|
_ => return None,
|
||||||
}
|
}
|
||||||
let (mut hi, body) = match self.toks.next()? {
|
let (mut hi, body, whole_body) = match self.toks.next()? {
|
||||||
TokenTree::Token(..) => return None,
|
TokenTree::Token(..) => return None,
|
||||||
TokenTree::Delimited(sp, _) => {
|
TokenTree::Delimited(sp, _) => {
|
||||||
let data = sp.data();
|
let data = sp.data();
|
||||||
(
|
(
|
||||||
data.hi,
|
data.hi,
|
||||||
Span::new(data.lo + BytePos(1), data.hi - BytePos(1), data.ctxt),
|
Span::new(data.lo + BytePos(1), data.hi - BytePos(1), data.ctxt),
|
||||||
|
sp,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -1191,6 +1204,7 @@ impl MacroParser {
|
||||||
args_paren_kind,
|
args_paren_kind,
|
||||||
args,
|
args,
|
||||||
body,
|
body,
|
||||||
|
whole_body,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1207,6 +1221,7 @@ struct MacroBranch {
|
||||||
args_paren_kind: DelimToken,
|
args_paren_kind: DelimToken,
|
||||||
args: ThinTokenStream,
|
args: ThinTokenStream,
|
||||||
body: Span,
|
body: Span,
|
||||||
|
whole_body: Span,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MacroBranch {
|
impl MacroBranch {
|
||||||
|
|
@ -1229,6 +1244,12 @@ impl MacroBranch {
|
||||||
result += " =>";
|
result += " =>";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !context.config.format_macro_bodies() {
|
||||||
|
result += " ";
|
||||||
|
result += context.snippet(self.whole_body);
|
||||||
|
return Some(result);
|
||||||
|
}
|
||||||
|
|
||||||
// The macro body is the most interesting part. It might end up as various
|
// The macro body is the most interesting part. It might end up as various
|
||||||
// AST nodes, but also has special variables (e.g, `$foo`) which can't be
|
// AST nodes, but also has special variables (e.g, `$foo`) which can't be
|
||||||
// parsed as regular Rust code (and note that these can be escaped using
|
// parsed as regular Rust code (and note that these can be escaped using
|
||||||
|
|
@ -1237,14 +1258,13 @@ impl MacroBranch {
|
||||||
|
|
||||||
let old_body = context.snippet(self.body).trim();
|
let old_body = context.snippet(self.body).trim();
|
||||||
let (body_str, substs) = replace_names(old_body)?;
|
let (body_str, substs) = replace_names(old_body)?;
|
||||||
|
let has_block_body = old_body.starts_with('{');
|
||||||
|
|
||||||
let mut config = context.config.clone();
|
let mut config = context.config.clone();
|
||||||
config.set().hide_parse_errors(true);
|
config.set().hide_parse_errors(true);
|
||||||
|
|
||||||
result += " {";
|
result += " {";
|
||||||
|
|
||||||
let has_block_body = old_body.starts_with('{');
|
|
||||||
|
|
||||||
let body_indent = if has_block_body {
|
let body_indent = if has_block_body {
|
||||||
shape.indent
|
shape.indent
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue