Skip to content

Commit

Permalink
Recover comments between attrs and generic param
Browse files Browse the repository at this point in the history
Fixes #5320.
  • Loading branch information
fee1-dead authored and calebcartwright committed Jun 12, 2023
1 parent e903fcd commit 5f9de6b
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 31 deletions.
4 changes: 4 additions & 0 deletions src/overflow.rs
Original file line number Diff line number Diff line change
Expand Up @@ -589,6 +589,8 @@ impl<'a> Context<'a> {

fn rewrite_items(&self) -> Option<(bool, String)> {
let span = self.items_span();
debug!("items: {:?}", self.items);

let items = itemize_list(
self.context.snippet_provider,
self.items.iter(),
Expand All @@ -603,6 +605,8 @@ impl<'a> Context<'a> {
);
let mut list_items: Vec<_> = items.collect();

debug!("items: {list_items:?}");

// Try letting the last argument overflow to the next line with block
// indentation. If its first line fits on one line with the other arguments,
// we format the function arguments horizontally.
Expand Down
76 changes: 45 additions & 31 deletions src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -572,49 +572,41 @@ impl Rewrite for ast::GenericBounds {

impl Rewrite for ast::GenericParam {
fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String> {
let mut result = String::with_capacity(128);
// FIXME: If there are more than one attributes, this will force multiline.
match self.attrs.rewrite(context, shape) {
Some(ref rw) if !rw.is_empty() => {
result.push_str(rw);
// When rewriting generic params, an extra newline should be put
// if the attributes end with a doc comment
if let Some(true) = self.attrs.last().map(|a| a.is_doc_comment()) {
result.push_str(&shape.indent.to_string_with_newline(context.config));
} else {
result.push(' ');
}
}
_ => (),
}
let mut result = self.attrs.rewrite(context, shape).unwrap_or(String::new());
let has_attrs = !result.is_empty();

if let ast::GenericParamKind::Const {
let mut param = String::with_capacity(128);

let param_start = if let ast::GenericParamKind::Const {
ref ty,
kw_span: _,
kw_span,
default,
} = &self.kind
{
result.push_str("const ");
result.push_str(rewrite_ident(context, self.ident));
result.push_str(": ");
result.push_str(&ty.rewrite(context, shape)?);
param.push_str("const ");
param.push_str(rewrite_ident(context, self.ident));
param.push_str(": ");
param.push_str(&ty.rewrite(context, shape)?);
if let Some(default) = default {
let eq_str = match context.config.type_punctuation_density() {
TypeDensity::Compressed => "=",
TypeDensity::Wide => " = ",
};
result.push_str(eq_str);
let budget = shape.width.checked_sub(result.len())?;
param.push_str(eq_str);
let budget = shape.width.checked_sub(param.len())?;
let rewrite = default.rewrite(context, Shape::legacy(budget, shape.indent))?;
result.push_str(&rewrite);
param.push_str(&rewrite);
}
kw_span.lo()
} else {
result.push_str(rewrite_ident(context, self.ident));
}
param.push_str(rewrite_ident(context, self.ident));
self.ident.span.lo()
};

if !self.bounds.is_empty() {
result.push_str(type_bound_colon(context));
result.push_str(&self.bounds.rewrite(context, shape)?)
param.push_str(type_bound_colon(context));
param.push_str(&self.bounds.rewrite(context, shape)?)
}
if let ast::GenericParamKind::Type {
default: Some(ref def),
Expand All @@ -624,11 +616,33 @@ impl Rewrite for ast::GenericParam {
TypeDensity::Compressed => "=",
TypeDensity::Wide => " = ",
};
result.push_str(eq_str);
let budget = shape.width.checked_sub(result.len())?;
param.push_str(eq_str);
let budget = shape.width.checked_sub(param.len())?;
let rewrite =
def.rewrite(context, Shape::legacy(budget, shape.indent + result.len()))?;
result.push_str(&rewrite);
def.rewrite(context, Shape::legacy(budget, shape.indent + param.len()))?;
param.push_str(&rewrite);
}

if let Some(last_attr) = self.attrs.last().filter(|last_attr| {
contains_comment(context.snippet(mk_sp(last_attr.span.hi(), param_start)))
}) {
result = combine_strs_with_missing_comments(
context,
&result,
&param,
mk_sp(last_attr.span.hi(), param_start),
shape,
!last_attr.is_doc_comment(),
)?;
} else {
// When rewriting generic params, an extra newline should be put
// if the attributes end with a doc comment
if let Some(true) = self.attrs.last().map(|a| a.is_doc_comment()) {
result.push_str(&shape.indent.to_string_with_newline(context.config));
} else if has_attrs {
result.push(' ');
}
result.push_str(&param);
}

Some(result)
Expand Down
18 changes: 18 additions & 0 deletions tests/target/doc-of-generic-item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,21 @@ struct Foo<
/// doc of N
const N: item,
>;

// Non-doc pre-comment of Foo
/// doc of Foo
// Non-doc post-comment of Foo
struct Foo<
// Non-doc pre-comment of 'a
/// doc of 'a
// Non-doc post-comment of 'a
'a,
// Non-doc pre-comment of T
/// doc of T
// Non-doc post-comment of T
T,
// Non-doc pre-comment of N
/// doc of N
// Non-doc post-comment of N
const N: item,
>;

0 comments on commit 5f9de6b

Please sign in to comment.