Skip to content

Multiline long params with attributes #4059

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

Closed
calebcartwright opened this issue Feb 19, 2020 · 1 comment · Fixed by #4455
Closed

Multiline long params with attributes #4059

calebcartwright opened this issue Feb 19, 2020 · 1 comment · Fixed by #4455
Labels
good first issue Issues up for grabs, also good candidates for new rustfmt contributors hacktoberfest help wanted poor-formatting

Comments

@calebcartwright
Copy link
Member

Formatting of params with attributes should be multilined if the formatting result length exceeds max_width.

rustfmt does this in the vast majority of cases, but there is currently an edge case where rustfmt falls back to the original one-line snippet for the param

this snippet:

fn a1(#[aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa] a: u8) {}

is formatted to:

fn a1(
    #[aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa] a: u8,
) {
}

It seems that all of the below conditions must be true in order for the line to not be split as desired:

  • only one attribute on the param
  • neither the attribute nor the param individually exceed the max width
  • param is named and not an empty infer/closure param
  • the combination of the formatted attributed and the param pattern is under the max width, but the addition of the colon and param type causes the total line length to exceed max width

I suspect that the rewrite for Param is what would need to be tweaked to handle this case:

fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String> {
let param_attrs_result = self
.attrs
.rewrite(context, Shape::legacy(shape.width, shape.indent))?;
let (span, has_multiple_attr_lines) = if !self.attrs.is_empty() {
let num_attrs = self.attrs.len();
(
mk_sp(self.attrs[num_attrs - 1].span.hi(), self.pat.span.lo()),
param_attrs_result.contains('\n'),
)
} else {
(mk_sp(self.span.lo(), self.span.lo()), false)
};
if let Some(ref explicit_self) = self.to_self() {
rewrite_explicit_self(
context,
explicit_self,
&param_attrs_result,
span,
shape,
has_multiple_attr_lines,
)
} else if is_named_param(self) {
let mut result = combine_strs_with_missing_comments(
context,
&param_attrs_result,
&self
.pat
.rewrite(context, Shape::legacy(shape.width, shape.indent))?,
span,
shape,
!has_multiple_attr_lines,
)?;
if !is_empty_infer(&*self.ty, self.pat.span) {
let (before_comment, after_comment) =
get_missing_param_comments(context, self.pat.span, self.ty.span, shape);
result.push_str(&before_comment);
result.push_str(colon_spaces(context.config));
result.push_str(&after_comment);
let overhead = last_line_width(&result);
let max_width = shape.width.checked_sub(overhead)?;
let ty_str = self
.ty
.rewrite(context, Shape::legacy(max_width, shape.indent))?;
result.push_str(&ty_str);
}
Some(result)
} else {
self.ty.rewrite(context, shape)
}
}

Refs #4047

@davidBar-On
Copy link
Contributor

Pull request #4390 hopefully resolve the issue. The problem is because the attribute and name are combined before the type is combined. The change is that name and type are combined together and then the result is combined with the attribute and comment.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
good first issue Issues up for grabs, also good candidates for new rustfmt contributors hacktoberfest help wanted poor-formatting
Projects
None yet
3 participants