Skip to content

Commit 378b28b

Browse files
authored
Merge pull request #3495 from scampi/issue-1096
keep missed comments appearing after the struct/enum ident
2 parents 77924a9 + bf383c4 commit 378b28b

File tree

4 files changed

+124
-25
lines changed

4 files changed

+124
-25
lines changed

src/comment.rs

+5
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,11 @@ fn comment_style(orig: &str, normalize_comments: bool) -> CommentStyle<'_> {
142142
}
143143
}
144144

145+
/// Returns true if the last line of the passed string finishes with a block-comment.
146+
pub fn is_last_comment_block(s: &str) -> bool {
147+
s.trim_end().ends_with("*/")
148+
}
149+
145150
/// Combine `prev_str` and `next_str` into a single `String`. `span` may contain
146151
/// comments between two strings. If there are such comments, then that will be
147152
/// recovered. If `allow_extend` is true and there is no comment between the two

src/items.rs

+46-23
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,9 @@ use syntax::visit;
1010
use syntax::{ast, ptr, symbol};
1111

1212
use crate::comment::{
13-
combine_strs_with_missing_comments, contains_comment, recover_comment_removed,
14-
recover_missing_comment_in_span, rewrite_missing_comment, FindUncommented,
13+
combine_strs_with_missing_comments, contains_comment, is_last_comment_block,
14+
recover_comment_removed, recover_missing_comment_in_span, rewrite_missing_comment,
15+
FindUncommented,
1516
};
1617
use crate::config::lists::*;
1718
use crate::config::{BraceStyle, Config, Density, IndentStyle, Version};
@@ -1173,11 +1174,7 @@ fn format_unit_struct(
11731174
) -> Option<String> {
11741175
let header_str = format_header(context, p.prefix, p.ident, p.vis);
11751176
let generics_str = if let Some(generics) = p.generics {
1176-
let hi = if generics.where_clause.predicates.is_empty() {
1177-
generics.span.hi()
1178-
} else {
1179-
generics.where_clause.span.hi()
1180-
};
1177+
let hi = context.snippet_provider.span_before(p.span, ";");
11811178
format_generics(
11821179
context,
11831180
generics,
@@ -2711,19 +2708,19 @@ fn format_generics(
27112708
let shape = Shape::legacy(context.budget(used_width + offset.width()), offset);
27122709
let mut result = rewrite_generics(context, "", generics, shape)?;
27132710

2714-
let same_line_brace = if !generics.where_clause.predicates.is_empty() || result.contains('\n') {
2711+
// If the generics are not parameterized then generics.span.hi() == 0,
2712+
// so we use span.lo(), which is the position after `struct Foo`.
2713+
let span_end_before_where = if !generics.params.is_empty() {
2714+
generics.span.hi()
2715+
} else {
2716+
span.lo()
2717+
};
2718+
let (same_line_brace, missed_comments) = if !generics.where_clause.predicates.is_empty() {
27152719
let budget = context.budget(last_line_used_width(&result, offset.width()));
27162720
let mut option = WhereClauseOption::snuggled(&result);
27172721
if brace_pos == BracePos::None {
27182722
option.suppress_comma = true;
27192723
}
2720-
// If the generics are not parameterized then generics.span.hi() == 0,
2721-
// so we use span.lo(), which is the position after `struct Foo`.
2722-
let span_end_before_where = if !generics.params.is_empty() {
2723-
generics.span.hi()
2724-
} else {
2725-
span.lo()
2726-
};
27272724
let where_clause_str = rewrite_where_clause(
27282725
context,
27292726
&generics.where_clause,
@@ -2737,15 +2734,41 @@ fn format_generics(
27372734
false,
27382735
)?;
27392736
result.push_str(&where_clause_str);
2740-
brace_pos == BracePos::ForceSameLine
2741-
|| brace_style == BraceStyle::PreferSameLine
2742-
|| (generics.where_clause.predicates.is_empty()
2743-
&& trimmed_last_line_width(&result) == 1)
2737+
(
2738+
brace_pos == BracePos::ForceSameLine || brace_style == BraceStyle::PreferSameLine,
2739+
// missed comments are taken care of in #rewrite_where_clause
2740+
None,
2741+
)
27442742
} else {
2745-
brace_pos == BracePos::ForceSameLine
2746-
|| trimmed_last_line_width(&result) == 1
2747-
|| brace_style != BraceStyle::AlwaysNextLine
2743+
(
2744+
brace_pos == BracePos::ForceSameLine
2745+
|| (result.contains('\n') && brace_style == BraceStyle::PreferSameLine
2746+
|| brace_style != BraceStyle::AlwaysNextLine)
2747+
|| trimmed_last_line_width(&result) == 1,
2748+
rewrite_missing_comment(
2749+
mk_sp(
2750+
span_end_before_where,
2751+
if brace_pos == BracePos::None {
2752+
span.hi()
2753+
} else {
2754+
context.snippet_provider.span_before(span, "{")
2755+
},
2756+
),
2757+
shape,
2758+
context,
2759+
),
2760+
)
27482761
};
2762+
// add missing comments
2763+
let missed_line_comments = missed_comments
2764+
.filter(|missed_comments| !missed_comments.is_empty())
2765+
.map_or(false, |missed_comments| {
2766+
let is_block = is_last_comment_block(&missed_comments);
2767+
let sep = if is_block { " " } else { "\n" };
2768+
result.push_str(sep);
2769+
result.push_str(&missed_comments);
2770+
!is_block
2771+
});
27492772
if brace_pos == BracePos::None {
27502773
return Some(result);
27512774
}
@@ -2761,7 +2784,7 @@ fn format_generics(
27612784
// 2 = ` {`
27622785
2
27632786
};
2764-
let forbid_same_line_brace = overhead > remaining_budget;
2787+
let forbid_same_line_brace = missed_line_comments || overhead > remaining_budget;
27652788
if !forbid_same_line_brace && same_line_brace {
27662789
result.push(' ');
27672790
} else {

src/missed_spans.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use std::borrow::Cow;
22

33
use syntax::source_map::{BytePos, Pos, Span};
44

5-
use crate::comment::{rewrite_comment, CodeCharKind, CommentCodeSlices};
5+
use crate::comment::{is_last_comment_block, rewrite_comment, CodeCharKind, CommentCodeSlices};
66
use crate::config::file_lines::FileLines;
77
use crate::config::{EmitMode, FileName};
88
use crate::shape::{Indent, Shape};
@@ -288,7 +288,7 @@ impl<'a> FmtVisitor<'a> {
288288
.next()
289289
{
290290
Some('\n') | Some('\r') => {
291-
if !subslice.trim_end().ends_with("*/") {
291+
if !is_last_comment_block(subslice) {
292292
self.push_str("\n");
293293
}
294294
}

tests/target/issue-1096.rs

+71
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
struct StructA<T> /* comment 1 */ {
2+
t: T,
3+
}
4+
5+
struct StructB<T> /* comment 2 */;
6+
7+
struct StructC /* comment 3 */;
8+
9+
struct StructD /* comment 4 */ {
10+
t: usize,
11+
}
12+
13+
struct StructE<T>
14+
/* comment 5 */
15+
where
16+
T: Clone,
17+
{
18+
t: usize,
19+
}
20+
21+
struct StructF
22+
/* comment 6 */
23+
where
24+
T: Clone,
25+
{
26+
t: usize,
27+
}
28+
29+
struct StructG<T>
30+
/* comment 7 */
31+
// why a line comment??
32+
{
33+
t: T,
34+
}
35+
36+
struct StructH<T>
37+
/* comment 8 */
38+
// why a line comment??
39+
where
40+
T: Clone,
41+
{
42+
t: T,
43+
}
44+
45+
enum EnumA<T> /* comment 8 */ {
46+
Field(T),
47+
}
48+
49+
enum EnumB /* comment 9 */ {
50+
Field,
51+
}
52+
53+
// Issue 2781
54+
struct StructX1<T>
55+
// where
56+
// T: Clone
57+
{
58+
inner: String,
59+
}
60+
61+
struct StructX2<
62+
T,
63+
U: Iterator<Item = String>,
64+
V: Iterator<Item = String>,
65+
W: Iterator<Item = String>,
66+
>
67+
// where
68+
// T: Clone
69+
{
70+
inner: String,
71+
}

0 commit comments

Comments
 (0)