Skip to content
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

keep missed comments appearing after the struct/enum ident #3495

Merged
merged 1 commit into from
Apr 9, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions src/comment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,11 @@ fn comment_style(orig: &str, normalize_comments: bool) -> CommentStyle<'_> {
}
}

/// Returns true if the last line of the passed string finishes with a block-comment.
pub fn is_last_comment_block(s: &str) -> bool {
s.trim_end().ends_with("*/")
}

/// Combine `prev_str` and `next_str` into a single `String`. `span` may contain
/// comments between two strings. If there are such comments, then that will be
/// recovered. If `allow_extend` is true and there is no comment between the two
Expand Down
69 changes: 46 additions & 23 deletions src/items.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,9 @@ use syntax::visit;
use syntax::{ast, ptr, symbol};

use crate::comment::{
combine_strs_with_missing_comments, contains_comment, recover_comment_removed,
recover_missing_comment_in_span, rewrite_missing_comment, FindUncommented,
combine_strs_with_missing_comments, contains_comment, is_last_comment_block,
recover_comment_removed, recover_missing_comment_in_span, rewrite_missing_comment,
FindUncommented,
};
use crate::config::lists::*;
use crate::config::{BraceStyle, Config, Density, IndentStyle, Version};
Expand Down Expand Up @@ -1173,11 +1174,7 @@ fn format_unit_struct(
) -> Option<String> {
let header_str = format_header(context, p.prefix, p.ident, p.vis);
let generics_str = if let Some(generics) = p.generics {
let hi = if generics.where_clause.predicates.is_empty() {
generics.span.hi()
} else {
generics.where_clause.span.hi()
};
let hi = context.snippet_provider.span_before(p.span, ";");
format_generics(
context,
generics,
Expand Down Expand Up @@ -2711,19 +2708,19 @@ fn format_generics(
let shape = Shape::legacy(context.budget(used_width + offset.width()), offset);
let mut result = rewrite_generics(context, "", generics, shape)?;

let same_line_brace = if !generics.where_clause.predicates.is_empty() || result.contains('\n') {
// If the generics are not parameterized then generics.span.hi() == 0,
// so we use span.lo(), which is the position after `struct Foo`.
let span_end_before_where = if !generics.params.is_empty() {
generics.span.hi()
} else {
span.lo()
};
let (same_line_brace, missed_comments) = if !generics.where_clause.predicates.is_empty() {
let budget = context.budget(last_line_used_width(&result, offset.width()));
let mut option = WhereClauseOption::snuggled(&result);
if brace_pos == BracePos::None {
option.suppress_comma = true;
}
// If the generics are not parameterized then generics.span.hi() == 0,
// so we use span.lo(), which is the position after `struct Foo`.
let span_end_before_where = if !generics.params.is_empty() {
generics.span.hi()
} else {
span.lo()
};
let where_clause_str = rewrite_where_clause(
context,
&generics.where_clause,
Expand All @@ -2737,15 +2734,41 @@ fn format_generics(
false,
)?;
result.push_str(&where_clause_str);
brace_pos == BracePos::ForceSameLine
|| brace_style == BraceStyle::PreferSameLine
|| (generics.where_clause.predicates.is_empty()
&& trimmed_last_line_width(&result) == 1)
(
brace_pos == BracePos::ForceSameLine || brace_style == BraceStyle::PreferSameLine,
// missed comments are taken care of in #rewrite_where_clause
None,
)
} else {
brace_pos == BracePos::ForceSameLine
|| trimmed_last_line_width(&result) == 1
|| brace_style != BraceStyle::AlwaysNextLine
(
brace_pos == BracePos::ForceSameLine
|| (result.contains('\n') && brace_style == BraceStyle::PreferSameLine
|| brace_style != BraceStyle::AlwaysNextLine)
|| trimmed_last_line_width(&result) == 1,
rewrite_missing_comment(
mk_sp(
span_end_before_where,
if brace_pos == BracePos::None {
span.hi()
} else {
context.snippet_provider.span_before(span, "{")
},
),
shape,
context,
),
)
};
// add missing comments
let missed_line_comments = missed_comments
.filter(|missed_comments| !missed_comments.is_empty())
.map_or(false, |missed_comments| {
let is_block = is_last_comment_block(&missed_comments);
let sep = if is_block { " " } else { "\n" };
result.push_str(sep);
result.push_str(&missed_comments);
!is_block
});
if brace_pos == BracePos::None {
return Some(result);
}
Expand All @@ -2761,7 +2784,7 @@ fn format_generics(
// 2 = ` {`
2
};
let forbid_same_line_brace = overhead > remaining_budget;
let forbid_same_line_brace = missed_line_comments || overhead > remaining_budget;
if !forbid_same_line_brace && same_line_brace {
result.push(' ');
} else {
Expand Down
4 changes: 2 additions & 2 deletions src/missed_spans.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use std::borrow::Cow;

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

use crate::comment::{rewrite_comment, CodeCharKind, CommentCodeSlices};
use crate::comment::{is_last_comment_block, rewrite_comment, CodeCharKind, CommentCodeSlices};
use crate::config::file_lines::FileLines;
use crate::config::{EmitMode, FileName};
use crate::shape::{Indent, Shape};
Expand Down Expand Up @@ -288,7 +288,7 @@ impl<'a> FmtVisitor<'a> {
.next()
{
Some('\n') | Some('\r') => {
if !subslice.trim_end().ends_with("*/") {
if !is_last_comment_block(subslice) {
self.push_str("\n");
}
}
Expand Down
71 changes: 71 additions & 0 deletions tests/target/issue-1096.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
struct StructA<T> /* comment 1 */ {
t: T,
}

struct StructB<T> /* comment 2 */;

struct StructC /* comment 3 */;

struct StructD /* comment 4 */ {
t: usize,
}

struct StructE<T>
/* comment 5 */
where
T: Clone,
{
t: usize,
}

struct StructF
/* comment 6 */
where
T: Clone,
{
t: usize,
}

struct StructG<T>
/* comment 7 */
// why a line comment??
{
t: T,
}

struct StructH<T>
/* comment 8 */
// why a line comment??
where
T: Clone,
{
t: T,
}

enum EnumA<T> /* comment 8 */ {
Field(T),
}

enum EnumB /* comment 9 */ {
Field,
}

// Issue 2781
struct StructX1<T>
// where
// T: Clone
{
inner: String,
}

struct StructX2<
T,
U: Iterator<Item = String>,
V: Iterator<Item = String>,
W: Iterator<Item = String>,
>
// where
// T: Clone
{
inner: String,
}