Skip to content

Indentation of asssignment comments between lhs and rhs#5501

Open
davidBar-On wants to merge 3 commits into
rust-lang:mainfrom
davidBar-On:issues-4661-4734-part5480-fromf897e25-Indentation-of-assignment-comments-between-lhs-and-rhs
Open

Indentation of asssignment comments between lhs and rhs#5501
davidBar-On wants to merge 3 commits into
rust-lang:mainfrom
davidBar-On:issues-4661-4734-part5480-fromf897e25-Indentation-of-assignment-comments-between-lhs-and-rhs

Conversation

@davidBar-On

Copy link
Copy Markdown
Contributor

Backport of suggested R2 changes for handling indentation of comments between assignment rhs and lhs, taken from different R2 PRs/commits. Not all changes were merged into R2, so this is why I didn't add "Backport" to the title.

Test cases are backport of PR #4734 test cases (which are enhancement of PR #4661 test cases).

The PR is based on:

Comment thread src/comment.rs Outdated
/// that end on that line.
fn is_first_comment_ends_on_first_line(s: &str) -> bool {
if s.starts_with("/*") {
s.lines().next().map_or(false, |l| l.contains("*/"))

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should we use ends_with instead of contains?

Suggested change
s.lines().next().map_or(false, |l| l.contains("*/"))
s.lines().next().map_or(false, |l| l.ends_with("*/"))

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed (although I am not sure whether the comment was deleted).
The main benefit of the change is that line that ends with /* comment 1*/ /* comment 2 is now properly handled. Therefore I also changed the function name and its description.

While evaluating the suggested change I found two issues that are worth noting:

  1. The following code is not handled properly and therefore is not formatted:
var= /* Block comment 1*/ // Line comment 2
value;

Fixing this is quite complex. Since it is not expected to be used much in practice, I assume that for this PR it is o.k. not to handle this case, but I did add FIXME comment for it.

  1. the following code (now added to the test cases):
var = /* Block comment */
value;

Is formatted into one line:

var = /* Block comment */ value;

However:

var = /* Block comment single line 1 */ 
/* Block comment single line 2*/ value;

is formatted as:

var = /* Block comment single line 1 */ 
    /* Block comment single line 2*/
    value;

I believe this is o.k., but I note that in case the formatted value in the first example should be in the next line.

Comment thread src/comment.rs Outdated
let one_line_width = last_line_width(prev_str) + first_line_width(&missing_comment) + 1;
if prefer_same_line && one_line_width <= shape.width {
// First comment of a comments block can be in same line if ends in the first line
// (and meets other conditions)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we enumerate what the other conditions are in the comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed - removed the "(and meets other conditions)" as it was redundant. Adding the additional details could just be confusing as the "other conditions" are clear from the code.

Comment thread src/comment.rs Outdated
Comment thread src/expr.rs Outdated
Comment thread src/items.rs
Comment thread src/comment.rs Outdated
Comment thread src/items.rs Outdated
Comment on lines +116 to +121
let base_span = if let Some(ref ty) = self.ty {
mk_sp(ty.span.hi(), self.span.hi())
} else {
mk_sp(self.pat.span.hi(), self.span.hi())
};

let offset = context.snippet(base_span).find_uncommented("=")?;
let base_span_lo = base_span.lo();

let assign_lo = base_span_lo + BytePos(offset as u32);
let comment_start_pos = if let Some(ref ty) = self.ty {
ty.span.hi()
} else {
self.pat.span.hi()
};
let comment_before_assign = context.snippet(mk_sp(comment_start_pos, assign_lo)).trim();

let assign_hi = base_span_lo + BytePos((offset + 1) as u32);
let rhs_span_lo = init.span.lo();
let comment_end_pos = if init.attrs.is_empty() {
rhs_span_lo
} else {
let attr_span_lo = init.attrs.first().unwrap().span.lo();
// for the case using block
// ex. let x = { #![my_attr]do_something(); }
if rhs_span_lo < attr_span_lo {
rhs_span_lo
} else {
attr_span_lo
}
};

if !comment_before_assign.is_empty() {
let new_indent_str = &pat_shape
.block_indent(0)
.to_string_with_newline(context.config);
result = format!("{}{}{}", comment_before_assign, new_indent_str, result);
}

@ytmimi ytmimi Oct 20, 2022

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Took some time to look into this code. It seems like a lot of what's going on here is to recover comments before the =, e.g. let pat: ty /*comment*/ = or let pat /*comment*/ =. However, this PR and all the test cases you've outlined below only test for comments that come after the = e.g. let pat: ty = /*comment*/ expr.

For that reason I think we should only worry about the post = comments in this PR.

I also propose renaming init to expr since I think it's a little clearer that it's an ast::Expr node, and using init() instead of init_else_opt() since we don't use the _else and currently don't support ast::LocalKind::InitElse(..) variants.

if let Some(expr) = self.kind.init() {
    // Adjust the span after the `pat` and `ty` before searching for the `=`
    let base_span = if let Some(ref ty) = self.ty {
        mk_sp(ty.span.hi(), self.span.hi())
    } else {
        mk_sp(self.pat.span.hi(), self.span.hi())
    };

    let comment_lo = context.snippet_provider.span_after(base_span, "=");
    let comment_span = mk_sp(comment_lo, expr.span.lo());

    let nested_shape = shape.sub_width(1)?;
    result = rewrite_assign_rhs_with_comments(
        context,
        result,
        expr,
        nested_shape,
        &RhsAssignKind::Expr(&expr.kind, expr.span),
        RhsTactics::Default,
        comment_span,
        true,
    )?;
}

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

... a lot of what's going on here is to recover comments before the =

I somehow missed that when I copied the R2 commit changes ☹️. I also checked now R2 and didn't find any test to the assign pre = comments. I therefore assume that maybe that commit was tested properly.

Changed the code per suggestion.

@ytmimi ytmimi left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks again for applying all the feedback, and for helping to backport those PRs! I think we're good to go here!

@ytmimi ytmimi added pr-ready-to-merge Status: PR is largely ready for merge, waiting for secondary review / last nits and removed pr-waiting-on-author labels Oct 27, 2022
@calebcartwright

Copy link
Copy Markdown
Member

I haven't had a chance to review this in detail, but from a cursory glance through the discussion and test cases my inclination is that this probably is the direction we want to go in long term.

However, it's got too big a risk of having a high blast radius for me to want to release it in the immediate future. I'd like to see this tested against some larger codebases, both to test/confirm that hypothesis/concern and see how it shakes out against a broader set of code.

Ultimately I think we'd need to version gate this no matter what, especially given the increased rigor around formatting stability given the pivot to style guide editions as the evolution mechanism

@davidBar-On davidBar-On force-pushed the issues-4661-4734-part5480-fromf897e25-Indentation-of-assignment-comments-between-lhs-and-rhs branch from c0c3b3e to d1da537 Compare February 7, 2023 14:45
@davidBar-On

Copy link
Copy Markdown
Contributor Author

Ultimately I think we'd need to version gate this no matter what ...

Added version gating.
Also rebased and consolidated all commits into one commit.

Comment thread src/items.rs Outdated
Comment thread src/items.rs Outdated
@ytmimi

ytmimi commented Feb 23, 2023

Copy link
Copy Markdown
Contributor

@davidBar-On thanks for making the requested changes. when you have a chance can you rebase your feature branch on master

@davidBar-On davidBar-On force-pushed the issues-4661-4734-part5480-fromf897e25-Indentation-of-assignment-comments-between-lhs-and-rhs branch from 1aa6ae0 to 81849b9 Compare February 23, 2023 19:37
@davidBar-On

Copy link
Copy Markdown
Contributor Author

... can you rebase your feature branch on master

Rebase done.

@ytmimi

ytmimi commented Feb 23, 2023

Copy link
Copy Markdown
Contributor

@calebcartwright I just ran the Diff Check Job, and with the version gate these changes don't produce any changes 👍🏼

@jieyouxu jieyouxu added the S-waiting-on-review Status: awaiting review from the assignee but also interested parties. label Feb 23, 2026
@rustbot

rustbot commented Mar 13, 2026

Copy link
Copy Markdown
Collaborator

☔ The latest upstream changes (possibly #6823) made this pull request unmergeable. Please resolve the merge conflicts.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

pr-ready-to-merge Status: PR is largely ready for merge, waiting for secondary review / last nits S-waiting-on-review Status: awaiting review from the assignee but also interested parties.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants