Skip to content

Commit 5f9de6b

Browse files
fee1-deadcalebcartwright
authored andcommitted
Recover comments between attrs and generic param
Fixes #5320.
1 parent e903fcd commit 5f9de6b

File tree

3 files changed

+67
-31
lines changed

3 files changed

+67
-31
lines changed

src/overflow.rs

+4
Original file line numberDiff line numberDiff line change
@@ -589,6 +589,8 @@ impl<'a> Context<'a> {
589589

590590
fn rewrite_items(&self) -> Option<(bool, String)> {
591591
let span = self.items_span();
592+
debug!("items: {:?}", self.items);
593+
592594
let items = itemize_list(
593595
self.context.snippet_provider,
594596
self.items.iter(),
@@ -603,6 +605,8 @@ impl<'a> Context<'a> {
603605
);
604606
let mut list_items: Vec<_> = items.collect();
605607

608+
debug!("items: {list_items:?}");
609+
606610
// Try letting the last argument overflow to the next line with block
607611
// indentation. If its first line fits on one line with the other arguments,
608612
// we format the function arguments horizontally.

src/types.rs

+45-31
Original file line numberDiff line numberDiff line change
@@ -572,49 +572,41 @@ impl Rewrite for ast::GenericBounds {
572572

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

591-
if let ast::GenericParamKind::Const {
579+
let mut param = String::with_capacity(128);
580+
581+
let param_start = if let ast::GenericParamKind::Const {
592582
ref ty,
593-
kw_span: _,
583+
kw_span,
594584
default,
595585
} = &self.kind
596586
{
597-
result.push_str("const ");
598-
result.push_str(rewrite_ident(context, self.ident));
599-
result.push_str(": ");
600-
result.push_str(&ty.rewrite(context, shape)?);
587+
param.push_str("const ");
588+
param.push_str(rewrite_ident(context, self.ident));
589+
param.push_str(": ");
590+
param.push_str(&ty.rewrite(context, shape)?);
601591
if let Some(default) = default {
602592
let eq_str = match context.config.type_punctuation_density() {
603593
TypeDensity::Compressed => "=",
604594
TypeDensity::Wide => " = ",
605595
};
606-
result.push_str(eq_str);
607-
let budget = shape.width.checked_sub(result.len())?;
596+
param.push_str(eq_str);
597+
let budget = shape.width.checked_sub(param.len())?;
608598
let rewrite = default.rewrite(context, Shape::legacy(budget, shape.indent))?;
609-
result.push_str(&rewrite);
599+
param.push_str(&rewrite);
610600
}
601+
kw_span.lo()
611602
} else {
612-
result.push_str(rewrite_ident(context, self.ident));
613-
}
603+
param.push_str(rewrite_ident(context, self.ident));
604+
self.ident.span.lo()
605+
};
614606

615607
if !self.bounds.is_empty() {
616-
result.push_str(type_bound_colon(context));
617-
result.push_str(&self.bounds.rewrite(context, shape)?)
608+
param.push_str(type_bound_colon(context));
609+
param.push_str(&self.bounds.rewrite(context, shape)?)
618610
}
619611
if let ast::GenericParamKind::Type {
620612
default: Some(ref def),
@@ -624,11 +616,33 @@ impl Rewrite for ast::GenericParam {
624616
TypeDensity::Compressed => "=",
625617
TypeDensity::Wide => " = ",
626618
};
627-
result.push_str(eq_str);
628-
let budget = shape.width.checked_sub(result.len())?;
619+
param.push_str(eq_str);
620+
let budget = shape.width.checked_sub(param.len())?;
629621
let rewrite =
630-
def.rewrite(context, Shape::legacy(budget, shape.indent + result.len()))?;
631-
result.push_str(&rewrite);
622+
def.rewrite(context, Shape::legacy(budget, shape.indent + param.len()))?;
623+
param.push_str(&rewrite);
624+
}
625+
626+
if let Some(last_attr) = self.attrs.last().filter(|last_attr| {
627+
contains_comment(context.snippet(mk_sp(last_attr.span.hi(), param_start)))
628+
}) {
629+
result = combine_strs_with_missing_comments(
630+
context,
631+
&result,
632+
&param,
633+
mk_sp(last_attr.span.hi(), param_start),
634+
shape,
635+
!last_attr.is_doc_comment(),
636+
)?;
637+
} else {
638+
// When rewriting generic params, an extra newline should be put
639+
// if the attributes end with a doc comment
640+
if let Some(true) = self.attrs.last().map(|a| a.is_doc_comment()) {
641+
result.push_str(&shape.indent.to_string_with_newline(context.config));
642+
} else if has_attrs {
643+
result.push(' ');
644+
}
645+
result.push_str(&param);
632646
}
633647

634648
Some(result)

tests/target/doc-of-generic-item.rs

+18
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,21 @@ struct Foo<
1212
/// doc of N
1313
const N: item,
1414
>;
15+
16+
// Non-doc pre-comment of Foo
17+
/// doc of Foo
18+
// Non-doc post-comment of Foo
19+
struct Foo<
20+
// Non-doc pre-comment of 'a
21+
/// doc of 'a
22+
// Non-doc post-comment of 'a
23+
'a,
24+
// Non-doc pre-comment of T
25+
/// doc of T
26+
// Non-doc post-comment of T
27+
T,
28+
// Non-doc pre-comment of N
29+
/// doc of N
30+
// Non-doc post-comment of N
31+
const N: item,
32+
>;

0 commit comments

Comments
 (0)