Skip to content

Format derive attributes vertically #5578

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

Open
BenLeadbetter opened this issue Oct 29, 2022 · 4 comments
Open

Format derive attributes vertically #5578

BenLeadbetter opened this issue Oct 29, 2022 · 4 comments

Comments

@BenLeadbetter
Copy link

Hi!

I'd like to format my #[derive(..)] attributes vertically - like this:

#[derive(
  Clone,
  Default,
  PartialEq,
)]

I've tried the following in my rustfmt.toml, but this seemed to have no effect.

attr_fn_like_width = 1 # no effect?
attr_fn_like_width = 0 # nor this

Also adding a trailing comma to the list doesn't work. rustfmt just removes the comma and reformats the list horizontally.

Any help appreciated!

@ytmimi
Copy link
Contributor

ytmimi commented Oct 29, 2022

Thanks for reaching out!

To the best of my knowledge there isn't a configuration that allows what you're looking for. I think we only format derives vertically if the derive list exceeds the max_width, which defaults to 100. Derives are formatted in format_derive, and we determine how the derives will be laid out here:

rustfmt/src/attr.rs

Lines 150 to 155 in ef91154

let tactic = definitive_tactic(
&all_items,
ListTactic::HorizontalVertical,
Separator::Comma,
argument_shape.width,
);

@BenLeadbetter
Copy link
Author

Cool! Thanks for the info.

So derive attributes do not fall into the attr_fn_like category?

If I have a go at implementing this feature, then handling derive statements directly is correct, right?

I just wonder whether there's a broader form that should be handled the same way? #[custom_attr(List, Of, Things)] for instance.

@ytmimi
Copy link
Contributor

ytmimi commented Oct 31, 2022

So derive attributes do not fall into the attr_fn_like category?

It would seem that derives are special cased. Likely because rustfmt provides the option to merge multiple derives into a single derive. For example this:

#[derive(Debug)]
#[derive(Clone)]
struct s;

could be formatted like:

#[derive(Debug, Clone)]
struct s;

If I have a go at implementing this feature, then handling derive statements directly is correct, right?

PRs are always welcome! Just a hunch, but you'll likely want to make changes to the lines of code I called out above where we determine what the tactic should be. It might be as simple as swapping argument_shape.width with context.config.attr_fn_like_width()

  let tactic = definitive_tactic( 
      &all_items, 
      ListTactic::HorizontalVertical, 
      Separator::Comma, 
-     argument_shape.width,
+     context.config.attr_fn_like_width()
 ); 

@ytmimi
Copy link
Contributor

ytmimi commented Oct 31, 2022

I just wonder whether there's a broader form that should be handled the same way? #[custom_attr(List, Of, Things)] for instance.

Just so you're aware those are handled here:

rustfmt/src/attr.rs

Lines 296 to 313 in ef91154

ast::MetaItemKind::List(ref list) => {
let path = rewrite_path(context, PathContext::Type, None, &self.path, shape)?;
let has_trailing_comma = crate::expr::span_ends_with_comma(context, self.span);
overflow::rewrite_with_parens(
context,
&path,
list.iter(),
// 1 = "]"
shape.sub_width(1)?,
self.span,
context.config.attr_fn_like_width(),
Some(if has_trailing_comma {
SeparatorTactic::Always
} else {
SeparatorTactic::Never
}),
)?
}

However, derive formatting is handled in format_derive as mentioned above, and it's likely that we can't reuse this code path because of the additional merging we might do when rewriting derives.

Hope all this info helps!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants