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

enhance const block formatting #4493

Merged
merged 1 commit into from
Nov 26, 2020
Merged

Conversation

frbimo
Copy link
Contributor

@frbimo frbimo commented Oct 25, 2020

Refs #4483

Testing
cargo make test

@frbimo frbimo force-pushed the const_block branch 2 times, most recently from 75180ed to a005a6c Compare October 27, 2020 07:17
@frbimo
Copy link
Contributor Author

frbimo commented Oct 27, 2020

...
fn foo() -> i32 {
    const // baz
{
        let x = 5 + 10;
        x / 3
    }
}

test snippet above i change it to

...
fn foo() -> i32 {
    const /* qux */
{
        let x = 5 + 10;
        x / 3
    }
}

because i can't find what is expected formatted result from comment with double slash.
@calebcartwright wdyt ?

@calebcartwright
Copy link
Member

calebcartwright commented Oct 30, 2020

Thank you for the PR @frbimo and apologies for the delay in review, has been a busy week for me. Could you rebase on master to grab the latest and make CI happy?

Edit: hold off on rebasing, we have a new/separate breaking rustc issue again that will prevent compiling on nightly 😞

@calebcartwright
Copy link
Member

because i can't find what is expected formatted result from comment with double slash.

In a case like this with comments between a keyword and an opening block we should try to respect the authors original comment placing as much as possible (combine_strs_with_missing_comments and recover_missing_comment_in_span do this best).

We should strive to maintain a comment placed on the same line as const regardless of whether it's a line or block comment, and the same is true if the author placed the comment on the following line.

So with input like this in a case where the a user has set brace_style to AlwaysNext line:

fn foo() -> i32 {
    const /* qux */ {
        let x = 5 + 10;
        x / 3
    }
    
    const
    /* qux */
    {
        let x = 5 + 10;
        x / 3
    }
    
    const // qux
    {
        let x = 5 + 10;
        x / 3
    }
    
    const
    // qux
    {
        let x = 5 + 10;
        x / 3
    }
}

the emitted formatting would be:

fn foo() -> i32 {
    const /* qux */
    {
        let x = 5 + 10;
        x / 3
    }
    
    const
    /* qux */
    {
        let x = 5 + 10;
        x / 3
    }
    
    const // qux
    {
        let x = 5 + 10;
        x / 3
    }
    
    const
    // qux
    {
        let x = 5 + 10;
        x / 3
    }
}

@frbimo
Copy link
Contributor Author

frbimo commented Nov 2, 2020

sorry if i made myself unclear, i forgot to mentioned i don't get the idea when the brace_style is default.
E.g

fn foo() -> i32 {
  const // qux
    {
        let x = 5 + 10;
        x / 3
    }
}

become like this (?)

fn foo() -> i32 {
  const // qux {
        let x = 5 + 10;
        x / 3
    }
}

@calebcartwright
Copy link
Member

become like this (?)

fn foo() -> i32 {
  const // qux {
        let x = 5 + 10;
        x / 3
    }
}

No, that would be bad for a few reasons. First, moving the opening bracket behind a line comment would result in breaking code as that bracket would be commented out. Second, and perhaps this is just indentation styles getting botched by GitHub, but the block contents and closing bracket for some reason have extra indentation which is also incorrect.

If there's a trailing line comment after the const keyword then the body has to go on the next line, regardless of brace style. You can observe this in practice already today with functions and structs.

Your snippet would be formatted as

fn foo() -> i32 {
    const // qux
    {
        let x = 5 + 10;
        x / 3
    }
}

As I mentioned above, some of the other comment utility functions may be easier to work with than rewrite_missing_comment in this since they will take care of a lot of this for you. rewrite_missing_comment will require piecing the full snippet together by hand, and will also fail to take into account the original comment placement

@frbimo
Copy link
Contributor Author

frbimo commented Nov 13, 2020

I can't ask for review or change label

@calebcartwright
Copy link
Member

I can't ask for review or change label

No worries, we get notifications when PRs are updated 👍

@calebcartwright
Copy link
Member

Things are looking good here @frbimo, will try to finish a final review over the weekend but think we're pretty close to being ready to merge

Copy link
Member

@calebcartwright calebcartwright left a comment

Choose a reason for hiding this comment

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

Thanks @frbimo! Apologies for the late review, have had limited bandwidth lately and have been spending most available cycles trying to get in front of some upstream changes.

The proposed changes seem to have the gist of what is needed, just want to refactor and clean up a bit. Have left some specifics inline for your review

src/formatting/expr.rs Outdated Show resolved Hide resolved
)?;

match context.config.brace_style() {
BraceStyle::AlwaysNextLine => Some(format!("{}", &combined_strs)),
Copy link
Member

Choose a reason for hiding this comment

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

Just a note that we wouldn't need to use format! here since we aren't joining any strings together, so Some(combined_strs) would have been fine here, though I think the body for this arm will need to change anyway.

If there's a comment in the between span then we could potentially utilize combine_strs_with_missing_comments, and could either have a couple arms with the comments check as a guard:

Suggested change
BraceStyle::AlwaysNextLine => Some(format!("{}", &combined_strs)),
BraceStyle::AlwaysNextLine if contains_comments => combine_strs_with_missing_comments(
context,
"const",
&anon_const_str,
between_span,
shape,
false,
),
BraceStyle::AlwaysNextLine => combine_strs_with_missing_comments(
context,
"const",
&anon_const_str,
between_span,
shape,
!anon_const_str.contains('\n'),
),

or just do something like this (could be helpful to include a comment somewhere nearby providing context for the conditional):

Suggested change
BraceStyle::AlwaysNextLine => Some(format!("{}", &combined_strs)),
BraceStyle::AlwaysNextLine => combine_strs_with_missing_comments(
context,
"const",
&anon_const_str,
between_span,
shape,
!contains_comments && !anon_const_str.contains('\n'),
),

Copy link
Contributor Author

Choose a reason for hiding this comment

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

a question, under AlwaysNextLine brace style, contains_comments value is constant (in this case is always false) thus i omit it.
Is there a reason to put it into the logic above? or the test case is not extensive enough?

Copy link
Member

Choose a reason for hiding this comment

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

a question, under AlwaysNextLine brace style, contains_comments value is constant (in this case is always false) thus i omit it.

So the two suggestions I provided were mutually exclusive suggestions.

One suggestion was to utilize two arms, with the first arm utilizing contains_comments as a guard, and in the second arm there was of course no need to utilize contains_comments in the arg to combine_strs_with_missing_comments.

The second suggestion, and the one I'd encourage, is a mutually exclusive alternative to the other suggestion, which only has a single arm that matches AlwaysNextLine (with no guard). In this model, the value of contains_comments is unknown, which is why it would need to be used for determining the value of the arg to use for the last/can_extend param in combine_strs_with_missing_comments.

Does that make sense, or were you asking a different question?

src/formatting/expr.rs Outdated Show resolved Hide resolved
Comment on lines +136 to +143
BraceStyle::AlwaysNextLine => combine_strs_with_missing_comments(
context,
"const",
&anon_const_str,
between_span,
shape,
!anon_const_str.contains('\n'),
),
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Does that make sense, or were you asking a different question?

somehow github doesn't show the update.
i have updated this according to your suggestion. one thing different is allow_extend value i put is without contains_comments as decision parameter because its value is constant. I did cargo make test with code as presented above and it passes the test.
My question is do we still need to put contains_comments here or the test is not extensive enough?

Copy link
Member

Choose a reason for hiding this comment

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

contains_comments as decision parameter because its value is constant

What makes you think that this value is constant? Whether this local has a value of true or false is explicitly variable depending on the input code being formatted

Copy link
Contributor Author

Choose a reason for hiding this comment

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

the fact that the code above (contains_comments is omitted) passed the test and successfuly built, i guess contains_comments is always false.
this certainly is my doubt whether i didn't put enough test case or contains_comments is constant.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

but this is just a question, at the moment i will follow your suggestion and later will update it with contains_comments on it.

Copy link
Member

Choose a reason for hiding this comment

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

the fact that the code above (contains_comments is omitted) passed the test and successfuly built, i guess contains_comments is always false.
this certainly is my doubt whether i didn't put enough test case or contains_comments is constant.

Ah okay, I think I see what you are asking now.

contains_comment is not a constant, but a utility function that provides the ability to cheaply peek into a certain span to see whether or not there are any comments within there. In this case, that span represents the section between the const keyword and the opening {. So with a const block expression like this: const { x }, contains_comment will return false because there are no comments there of course, but with an expression like const /*abc*/ { x }, contains_comment will return true because there is of course a comment within /*abc*/.

The reason why I included this was to try to be consistent with how rustfmt currently handles comments between the unsafe keyword and the associated block when brace_style is set to AlwaysNextLine:

fn foo() {
    unsafe /*x*/
    {
        y
    }
}

However, and perhaps this is what you were alluding to 😄, it's not necessary to do so here because combine_strs_with_missing_comments already takes this into account!

Sorry about that, I was going back and forth in my head about which util functions to use and got a bit mixed up. If you wouldn't mind reverting that back (removing the ! contains_comments) then we should be good to merge this. Thanks for your patience and persistence!

Copy link
Contributor Author

Choose a reason for hiding this comment

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

sorry, i cant formulate a good sentences.

Signed-off-by: frbimo <fr.bimo@gmail.com>
@calebcartwright
Copy link
Member

Thanks! Don't worry about the CI checks, it's a toolstate issue that's being addressed separately.

@calebcartwright calebcartwright merged commit e358d19 into rust-lang:master Nov 26, 2020
@ytmimi ytmimi added 1x-backport:pending Fixed/resolved in source but not yet backported to a 1x branch and release and removed backport-triage labels Apr 1, 2022
@ytmimi ytmimi mentioned this pull request Apr 1, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
1x-backport:pending Fixed/resolved in source but not yet backported to a 1x branch and release
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants