diff --git a/src/overflow.rs b/src/overflow.rs index af0b95430a1..d81bf24dbd1 100644 --- a/src/overflow.rs +++ b/src/overflow.rs @@ -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(), @@ -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. diff --git a/src/types.rs b/src/types.rs index 01e2fb6e61e..b4be6546efb 100644 --- a/src/types.rs +++ b/src/types.rs @@ -572,49 +572,41 @@ impl Rewrite for ast::GenericBounds { impl Rewrite for ast::GenericParam { fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option { - 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), @@ -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, + ¶m, + 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(¶m); } Some(result) diff --git a/tests/target/doc-of-generic-item.rs b/tests/target/doc-of-generic-item.rs index 2efc5e09a3d..80886e74f83 100644 --- a/tests/target/doc-of-generic-item.rs +++ b/tests/target/doc-of-generic-item.rs @@ -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, +>;