Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add unstable format_brace_macros option #5538

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 21 additions & 1 deletion Configurations.md
Original file line number Diff line number Diff line change
Expand Up @@ -1098,7 +1098,7 @@ See also [`format_macro_bodies`](#format_macro_bodies).

## `format_macro_bodies`

Format the bodies of macros.
Format the bodies of declarative macro definitions.

- **Default value**: `true`
- **Possible values**: `true`, `false`
Expand Down Expand Up @@ -1128,6 +1128,26 @@ macro_rules! foo {

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

## `format_brace_macros`

Format the contents of fn-like macro invocations that use brace delimiters.

- **Default value**: `true`
- **Possible values**: `true`, `false`
- **Stable**: No
trevyn marked this conversation as resolved.
Show resolved Hide resolved

#### `true` (default):

```rust
foo! { "bar" }
```

#### `false`:

```rust
foo! {"bar"}
```

## `skip_macro_invocations`

Skip formatting the bodies of macro invocations with the following names.
Expand Down
5 changes: 4 additions & 1 deletion src/config/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,9 @@ create_config! {
format_strings: bool, false, false, "Format string literals where necessary";
format_macro_matchers: bool, false, false,
"Format the metavariable matching patterns in macros";
format_macro_bodies: bool, true, false, "Format the bodies of macros";
format_macro_bodies: bool, true, false, "Format the bodies of declarative macro definitions";
format_brace_macros: bool, true, false,
"Format the contents of fn-like macro invocations that use brace delimiters";
skip_macro_invocations: MacroSelectors, MacroSelectors::default(), false,
"Skip formatting the bodies of macros invoked with the following names.";
hex_literal_case: HexLiteralCase, HexLiteralCase::Preserve, false,
Expand Down Expand Up @@ -628,6 +630,7 @@ normalize_doc_attributes = false
format_strings = false
format_macro_matchers = false
format_macro_bodies = true
format_brace_macros = true
skip_macro_invocations = []
hex_literal_case = "Preserve"
empty_item_single_line = true
Expand Down
56 changes: 42 additions & 14 deletions src/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,7 @@ fn rewrite_macro_inner(
original_style
};

let ts = mac.args.inner_tokens();
let mut ts = mac.args.inner_tokens();
let has_comment = contains_comment(context.snippet(mac.span()));
if ts.is_empty() && !has_comment {
return match style {
Expand All @@ -232,23 +232,37 @@ fn rewrite_macro_inner(
}
}

if Delimiter::Brace == style && context.config.format_brace_macros() {
if let ast::MacArgs::Delimited(span, ..) = *mac.args {
ts = TokenStream::new(vec![TokenTree::Delimited(span, Delimiter::Brace, ts)]);
}
}

let ParsedMacroArgs {
args: arg_vec,
vec_with_semi,
trailing_comma,
} = match parse_macro_args(context, ts, style, is_forced_bracket) {
Some(args) => args,
None => {
return return_macro_parse_failure_fallback(
context,
shape.indent,
position,
mac.span(),
);
} = if Delimiter::Brace == style && !context.config.format_brace_macros() {
ParsedMacroArgs::default()
} else {
match parse_macro_args(context, ts, is_forced_bracket) {
Some(args) => args,
None => {
if Delimiter::Brace == style {
ParsedMacroArgs::default()
} else {
return return_macro_parse_failure_fallback(
context,
shape.indent,
position,
mac.span(),
);
}
}
}
};

if !arg_vec.is_empty() && arg_vec.iter().all(MacroArg::is_item) {
if !arg_vec.is_empty() && arg_vec.iter().all(MacroArg::is_item) && Delimiter::Brace != style {
return rewrite_macro_with_items(
context,
&arg_vec,
Expand Down Expand Up @@ -325,10 +339,24 @@ fn rewrite_macro_inner(
}
}
Delimiter::Brace => {
let snippet = if arg_vec.is_empty() {
None
} else {
overflow::rewrite_undelimited(
context,
&macro_name,
arg_vec.iter(),
shape,
mac.span(),
context.config.fn_call_width(),
None,
)
}
.unwrap_or(context.snippet(mac.span()).into());

// For macro invocations with braces, always put a space between
// the `macro_name!` and `{ /* macro_body */ }` but skip modifying
// anything in between the braces (for now).
let snippet = context.snippet(mac.span()).trim_start_matches(|c| c != '{');
// the `macro_name!` and `{ /* macro_body */ }`.
let snippet = snippet.trim_start_matches(|c| c != '{');
match trim_left_preserve_layout(snippet, shape.indent, context.config) {
Some(macro_body) => Some(format!("{} {}", macro_name, macro_body)),
None => Some(format!("{} {}", macro_name, snippet)),
Expand Down
24 changes: 24 additions & 0 deletions src/overflow.rs
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,30 @@ pub(crate) fn rewrite_with_parens<'a, T: 'a + IntoOverflowableItem<'a>>(
.rewrite(shape)
}

pub(crate) fn rewrite_undelimited<'a, T: 'a + IntoOverflowableItem<'a>>(
context: &'a RewriteContext<'_>,
ident: &'a str,
items: impl Iterator<Item = &'a T>,
shape: Shape,
span: Span,
item_max_width: usize,
force_separator_tactic: Option<SeparatorTactic>,
) -> Option<String> {
Context::new(
context,
items,
ident,
shape,
span,
"",
"",
item_max_width,
force_separator_tactic,
None,
)
.rewrite(shape)
}

pub(crate) fn rewrite_with_angle_brackets<'a, T: 'a + IntoOverflowableItem<'a>>(
context: &'a RewriteContext<'_>,
ident: &'a str,
Expand Down
74 changes: 36 additions & 38 deletions src/parse/macros/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use rustc_ast::token::{Delimiter, TokenKind};
use rustc_ast::token::TokenKind;
use rustc_ast::tokenstream::TokenStream;
use rustc_ast::{ast, ptr};
use rustc_parse::parser::{ForceCollect, Parser};
Expand Down Expand Up @@ -69,6 +69,7 @@ fn parse_macro_arg<'a, 'b: 'a>(parser: &'a mut Parser<'b>) -> Option<MacroArg> {
None
}

#[derive(Default)]
pub(crate) struct ParsedMacroArgs {
pub(crate) vec_with_semi: bool,
pub(crate) trailing_comma: bool,
Expand All @@ -95,59 +96,56 @@ fn check_keyword<'a, 'b: 'a>(parser: &'a mut Parser<'b>) -> Option<MacroArg> {
pub(crate) fn parse_macro_args(
context: &RewriteContext<'_>,
tokens: TokenStream,
style: Delimiter,
forced_bracket: bool,
) -> Option<ParsedMacroArgs> {
let mut parser = build_parser(context, tokens);
let mut args = Vec::new();
let mut vec_with_semi = false;
let mut trailing_comma = false;

if Delimiter::Brace != style {
loop {
if let Some(arg) = check_keyword(&mut parser) {
args.push(arg);
} else if let Some(arg) = parse_macro_arg(&mut parser) {
args.push(arg);
} else {
return None;
}
loop {
if let Some(arg) = check_keyword(&mut parser) {
args.push(arg);
} else if let Some(arg) = parse_macro_arg(&mut parser) {
args.push(arg);
} else {
return None;
}

match parser.token.kind {
TokenKind::Eof => break,
TokenKind::Comma => (),
TokenKind::Semi => {
// Try to parse `vec![expr; expr]`
if forced_bracket {
parser.bump();
if parser.token.kind != TokenKind::Eof {
match parse_macro_arg(&mut parser) {
Some(arg) => {
args.push(arg);
parser.bump();
if parser.token.kind == TokenKind::Eof && args.len() == 2 {
vec_with_semi = true;
break;
}
}
None => {
return None;
match parser.token.kind {
TokenKind::Eof => break,
TokenKind::Comma => (),
TokenKind::Semi => {
// Try to parse `vec![expr; expr]`
if forced_bracket {
parser.bump();
if parser.token.kind != TokenKind::Eof {
match parse_macro_arg(&mut parser) {
Some(arg) => {
args.push(arg);
parser.bump();
if parser.token.kind == TokenKind::Eof && args.len() == 2 {
vec_with_semi = true;
break;
}
}
None => {
return None;
}
}
}
return None;
}
_ if args.last().map_or(false, MacroArg::is_item) => continue,
_ => return None,
return None;
}
_ if args.last().map_or(false, MacroArg::is_item) => continue,
_ => return None,
}

parser.bump();
parser.bump();

if parser.token.kind == TokenKind::Eof {
trailing_comma = true;
break;
}
if parser.token.kind == TokenKind::Eof {
trailing_comma = true;
break;
}
}

Expand Down
Loading