Skip to content

Commit a6f7025

Browse files
committed
Add unstable format_brace_macros option
1 parent 38659ec commit a6f7025

File tree

17 files changed

+985
-54
lines changed

17 files changed

+985
-54
lines changed

Configurations.md

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1098,7 +1098,7 @@ See also [`format_macro_bodies`](#format_macro_bodies).
10981098

10991099
## `format_macro_bodies`
11001100

1101-
Format the bodies of macros.
1101+
Format the bodies of declarative macro definitions.
11021102

11031103
- **Default value**: `true`
11041104
- **Possible values**: `true`, `false`
@@ -1128,6 +1128,26 @@ macro_rules! foo {
11281128

11291129
See also [`format_macro_matchers`](#format_macro_matchers).
11301130

1131+
## `format_brace_macros`
1132+
1133+
Format the contents of fn-like macro invocations that use brace delimiters.
1134+
1135+
- **Default value**: `true`
1136+
- **Possible values**: `true`, `false`
1137+
- **Stable**: No
1138+
1139+
#### `true` (default):
1140+
1141+
```rust
1142+
foo! { "bar" }
1143+
```
1144+
1145+
#### `false`:
1146+
1147+
```rust
1148+
foo! {"bar"}
1149+
```
1150+
11311151
## `skip_macro_invocations`
11321152

11331153
Skip formatting the bodies of macro invocations with the following names.

src/config/mod.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,9 @@ create_config! {
7171
format_strings: bool, false, false, "Format string literals where necessary";
7272
format_macro_matchers: bool, false, false,
7373
"Format the metavariable matching patterns in macros";
74-
format_macro_bodies: bool, true, false, "Format the bodies of macros";
74+
format_macro_bodies: bool, true, false, "Format the bodies of declarative macro definitions";
75+
format_brace_macros: bool, true, false,
76+
"Format the contents of fn-like macro invocations that use brace delimiters";
7577
skip_macro_invocations: MacroSelectors, MacroSelectors::default(), false,
7678
"Skip formatting the bodies of macros invoked with the following names.";
7779
hex_literal_case: HexLiteralCase, HexLiteralCase::Preserve, false,
@@ -628,6 +630,7 @@ normalize_doc_attributes = false
628630
format_strings = false
629631
format_macro_matchers = false
630632
format_macro_bodies = true
633+
format_brace_macros = true
631634
skip_macro_invocations = []
632635
hex_literal_case = "Preserve"
633636
empty_item_single_line = true

src/macros.rs

Lines changed: 42 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,7 @@ fn rewrite_macro_inner(
209209
original_style
210210
};
211211

212-
let ts = mac.args.inner_tokens();
212+
let mut ts = mac.args.inner_tokens();
213213
let has_comment = contains_comment(context.snippet(mac.span()));
214214
if ts.is_empty() && !has_comment {
215215
return match style {
@@ -232,23 +232,37 @@ fn rewrite_macro_inner(
232232
}
233233
}
234234

235+
if Delimiter::Brace == style && context.config.format_brace_macros() {
236+
if let ast::MacArgs::Delimited(span, ..) = *mac.args {
237+
ts = TokenStream::new(vec![TokenTree::Delimited(span, Delimiter::Brace, ts)]);
238+
}
239+
}
240+
235241
let ParsedMacroArgs {
236242
args: arg_vec,
237243
vec_with_semi,
238244
trailing_comma,
239-
} = match parse_macro_args(context, ts, style, is_forced_bracket) {
240-
Some(args) => args,
241-
None => {
242-
return return_macro_parse_failure_fallback(
243-
context,
244-
shape.indent,
245-
position,
246-
mac.span(),
247-
);
245+
} = if Delimiter::Brace == style && !context.config.format_brace_macros() {
246+
ParsedMacroArgs::default()
247+
} else {
248+
match parse_macro_args(context, ts, is_forced_bracket) {
249+
Some(args) => args,
250+
None => {
251+
if Delimiter::Brace == style {
252+
ParsedMacroArgs::default()
253+
} else {
254+
return return_macro_parse_failure_fallback(
255+
context,
256+
shape.indent,
257+
position,
258+
mac.span(),
259+
);
260+
}
261+
}
248262
}
249263
};
250264

251-
if !arg_vec.is_empty() && arg_vec.iter().all(MacroArg::is_item) {
265+
if !arg_vec.is_empty() && arg_vec.iter().all(MacroArg::is_item) && Delimiter::Brace != style {
252266
return rewrite_macro_with_items(
253267
context,
254268
&arg_vec,
@@ -325,10 +339,24 @@ fn rewrite_macro_inner(
325339
}
326340
}
327341
Delimiter::Brace => {
342+
let snippet = if arg_vec.is_empty() {
343+
None
344+
} else {
345+
overflow::rewrite_undelimited(
346+
context,
347+
&macro_name,
348+
arg_vec.iter(),
349+
shape,
350+
mac.span(),
351+
context.config.fn_call_width(),
352+
None,
353+
)
354+
}
355+
.unwrap_or(context.snippet(mac.span()).into());
356+
328357
// For macro invocations with braces, always put a space between
329-
// the `macro_name!` and `{ /* macro_body */ }` but skip modifying
330-
// anything in between the braces (for now).
331-
let snippet = context.snippet(mac.span()).trim_start_matches(|c| c != '{');
358+
// the `macro_name!` and `{ /* macro_body */ }`.
359+
let snippet = snippet.trim_start_matches(|c| c != '{');
332360
match trim_left_preserve_layout(snippet, shape.indent, context.config) {
333361
Some(macro_body) => Some(format!("{} {}", macro_name, macro_body)),
334362
None => Some(format!("{} {}", macro_name, snippet)),

src/overflow.rs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,30 @@ pub(crate) fn rewrite_with_parens<'a, T: 'a + IntoOverflowableItem<'a>>(
268268
.rewrite(shape)
269269
}
270270

271+
pub(crate) fn rewrite_undelimited<'a, T: 'a + IntoOverflowableItem<'a>>(
272+
context: &'a RewriteContext<'_>,
273+
ident: &'a str,
274+
items: impl Iterator<Item = &'a T>,
275+
shape: Shape,
276+
span: Span,
277+
item_max_width: usize,
278+
force_separator_tactic: Option<SeparatorTactic>,
279+
) -> Option<String> {
280+
Context::new(
281+
context,
282+
items,
283+
ident,
284+
shape,
285+
span,
286+
"",
287+
"",
288+
item_max_width,
289+
force_separator_tactic,
290+
None,
291+
)
292+
.rewrite(shape)
293+
}
294+
271295
pub(crate) fn rewrite_with_angle_brackets<'a, T: 'a + IntoOverflowableItem<'a>>(
272296
context: &'a RewriteContext<'_>,
273297
ident: &'a str,

src/parse/macros/mod.rs

Lines changed: 36 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use rustc_ast::token::{Delimiter, TokenKind};
1+
use rustc_ast::token::TokenKind;
22
use rustc_ast::tokenstream::TokenStream;
33
use rustc_ast::{ast, ptr};
44
use rustc_parse::parser::{ForceCollect, Parser};
@@ -69,6 +69,7 @@ fn parse_macro_arg<'a, 'b: 'a>(parser: &'a mut Parser<'b>) -> Option<MacroArg> {
6969
None
7070
}
7171

72+
#[derive(Default)]
7273
pub(crate) struct ParsedMacroArgs {
7374
pub(crate) vec_with_semi: bool,
7475
pub(crate) trailing_comma: bool,
@@ -95,59 +96,56 @@ fn check_keyword<'a, 'b: 'a>(parser: &'a mut Parser<'b>) -> Option<MacroArg> {
9596
pub(crate) fn parse_macro_args(
9697
context: &RewriteContext<'_>,
9798
tokens: TokenStream,
98-
style: Delimiter,
9999
forced_bracket: bool,
100100
) -> Option<ParsedMacroArgs> {
101101
let mut parser = build_parser(context, tokens);
102102
let mut args = Vec::new();
103103
let mut vec_with_semi = false;
104104
let mut trailing_comma = false;
105105

106-
if Delimiter::Brace != style {
107-
loop {
108-
if let Some(arg) = check_keyword(&mut parser) {
109-
args.push(arg);
110-
} else if let Some(arg) = parse_macro_arg(&mut parser) {
111-
args.push(arg);
112-
} else {
113-
return None;
114-
}
106+
loop {
107+
if let Some(arg) = check_keyword(&mut parser) {
108+
args.push(arg);
109+
} else if let Some(arg) = parse_macro_arg(&mut parser) {
110+
args.push(arg);
111+
} else {
112+
return None;
113+
}
115114

116-
match parser.token.kind {
117-
TokenKind::Eof => break,
118-
TokenKind::Comma => (),
119-
TokenKind::Semi => {
120-
// Try to parse `vec![expr; expr]`
121-
if forced_bracket {
122-
parser.bump();
123-
if parser.token.kind != TokenKind::Eof {
124-
match parse_macro_arg(&mut parser) {
125-
Some(arg) => {
126-
args.push(arg);
127-
parser.bump();
128-
if parser.token.kind == TokenKind::Eof && args.len() == 2 {
129-
vec_with_semi = true;
130-
break;
131-
}
132-
}
133-
None => {
134-
return None;
115+
match parser.token.kind {
116+
TokenKind::Eof => break,
117+
TokenKind::Comma => (),
118+
TokenKind::Semi => {
119+
// Try to parse `vec![expr; expr]`
120+
if forced_bracket {
121+
parser.bump();
122+
if parser.token.kind != TokenKind::Eof {
123+
match parse_macro_arg(&mut parser) {
124+
Some(arg) => {
125+
args.push(arg);
126+
parser.bump();
127+
if parser.token.kind == TokenKind::Eof && args.len() == 2 {
128+
vec_with_semi = true;
129+
break;
135130
}
136131
}
132+
None => {
133+
return None;
134+
}
137135
}
138136
}
139-
return None;
140137
}
141-
_ if args.last().map_or(false, MacroArg::is_item) => continue,
142-
_ => return None,
138+
return None;
143139
}
140+
_ if args.last().map_or(false, MacroArg::is_item) => continue,
141+
_ => return None,
142+
}
144143

145-
parser.bump();
144+
parser.bump();
146145

147-
if parser.token.kind == TokenKind::Eof {
148-
trailing_comma = true;
149-
break;
150-
}
146+
if parser.token.kind == TokenKind::Eof {
147+
trailing_comma = true;
148+
break;
151149
}
152150
}
153151

0 commit comments

Comments
 (0)