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

Fixed first comment and last comment not reordering issue #4504

Open
wants to merge 4 commits into
base: rustfmt-2.0.0-rc.2
Choose a base branch
from

Conversation

whizsid
Copy link
Contributor

@whizsid whizsid commented Oct 30, 2020

Fixes #4027 .

@calebcartwright
Copy link
Member

calebcartwright commented Oct 30, 2020

Thanks @whizsid! Note CI is failing and we're blocked on rust-lang/rust#78549

@calebcartwright
Copy link
Member

Blocking issues should be resolved. When you get a chance can you rebase on master to grab the latest and get CI passing?

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 so much @whizsid! Minor change requested and a few nits/cleanup suggestions but looking pretty good!

Comment on lines 332 to 336
if !first
&& (!inner_item.is_empty()
|| item.post_comment.is_some()
|| item.pre_comment.is_some())
&& !result.is_empty() =>
Copy link
Member

Choose a reason for hiding this comment

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

This guard is starting to get pretty gnarly. Could you refactor it a bit to improve readability? We don't have any other subsequent Vertical arms, so I suppose some of these checks could be moved into the body (since it's a noop if conditions aren't met).

For example i think to keep this in the guard we'd want to potentially shift this to some locals like

let item_has_comments = item.post_comment.is_some() || item.pre_comment.is_some();
// or
let non_empty_or_comments = !inner_item.is_empty() || item.post_comment.is_some() || item.pre_comment.is_some();

Otherwise I think it'd probably be much more readable to reduce the guard conditions and use these checks in the body to determine whether to push.

Also could we just do a single result.push(newline_str) now since that's declared above (vs. result.push('\n'); result.push(indent_str);)

Comment on lines +500 to +505
if !inner_item.is_empty()
&& (!formatting.align_comments
|| (last
&& item_max_width.is_some()
&& !separate
&& !formatting.separator.is_empty()))
Copy link
Member

Choose a reason for hiding this comment

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

I know this one was already pretty busy but the extra condition and subsequent indentation is a bit of an eye sore. I guess it'd be okay but I also wouldn't mind seeing some minor refactoring of this existing code too

self.inner.peek().is_none(),
);
let comment_end =
if next_item.is_none() && last_line_contains_single_line_comment(post_snippet) {
Copy link
Member

Choose a reason for hiding this comment

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

what condition is the comment check for? a small example snippet would be helpful, my mental runtime is failing me 😄

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@calebcartwright The trailing comment of last item is not capturing for the item list. So I put this condition to take the trailing comment if it in the same line.

Without this condition:-

use c; // cpost
use b; // bpost
use a; // Trailing comment of last item

formatting to

use a;
use b; // bpost
use c; // cpost // Trailing comment of last item

@@ -397,7 +405,9 @@ where
item_max_width = None;
}

if separate && sep_place.is_front() && !first {
if inner_item.is_empty() && item.pre_comment.is_some() && item.post_comment.is_some() {
Copy link
Member

Choose a reason for hiding this comment

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

This is okay on its own, though along the same lines as the above comment I think declaring a local like item_has_comments and reusing could simplify some of these conditionals

Comment on lines 192 to 199
pub(crate) fn line_bounds(&self, pos: BytePos) -> (BytePos, BytePos) {
let line = self.parse_sess.source_map().lookup_line(pos).ok();

match line {
Some(line_info) => line_info.sf.line_bounds(line_info.line),
None => (BytePos::from_usize(0), BytePos::from_usize(0)),
}
}
Copy link
Member

Choose a reason for hiding this comment

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

Hmmm, I don't think we'll want to silently map a source map lookup error to hi/lo 0 like this. It doesn't really seem a likely condition but I have a nagging suspicion it could eventually be hit which would cause some weird formatting behavior.

Probably best to set the return type to an option containing tuple, and then call explicitly unwrap from the caller to panic and fail loudly in that hypothetical case

@@ -0,0 +1,30 @@
mod a;
Copy link
Member

Choose a reason for hiding this comment

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

Love the thoroughness of the tests ❤️ Would you mind either:

It's really helpful for long term maintenance to structure the tests in such a way that issue-specific fixes/tests can be tied back directly

@whizsid
Copy link
Contributor Author

whizsid commented Feb 20, 2021

@calebcartwright I adjusted my PR. can you review again?

@calebcartwright
Copy link
Member

@calebcartwright I adjusted my PR. can you review again?

Thanks for the updates! This PR has been sitting out here for a while though, would you please rebase on master?

@@ -482,19 +481,88 @@ where
let width = formatting.shape.width.checked_sub(overhead).unwrap_or(1);
let offset = formatting.shape.indent + overhead;

let comment_shape = Shape::legacy(width, offset);
Copy link
Contributor Author

Choose a reason for hiding this comment

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

@calebcartwright I rebased with the master branch at the earlier commit. Accidentally I worked in the same commit that resolving the conflicts. L485-L565 lines from the last conflicted commit.

Copy link
Member

Choose a reason for hiding this comment

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

Cheers. That's not too surprising given the age, though I'll need to squash anyway give the merge commit.

I should finally have a bit of bandwidth in the next day or two to get back to the PR queue so will hopefully be able to review soon.

For future reference/PRs though it'd be helpful if to just do a clean rebase of your topic branch on the upstream branch from this repo and avoid merge commits 👍 Thanks again for all your work!

@calebcartwright
Copy link
Member

While there's a few nits I do think the approach seems reasonable, and the resulting formatting is certainly better than what it exists today (some of these snippets get horribly butchered today).

I'd like to add a couple more test cases before merging though, just to be extra cautious. Could you add a couple snippets to cover the following:

  • A trailing mix of a block comment followed by a line comment (use foo; /* bar */ // evil
  • Multiline block comments
  • imports within indented scopes (e.g inside an inline module, function, etc.)

After those tests are added, should be good to merge

@calebcartwright calebcartwright changed the base branch from master to rustfmt-2.0.0-rc.2 April 30, 2021 00:22
@ytmimi ytmimi added pr-targeting-2.0 This PR is targeting the 2.0 branch p-low labels Jul 27, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
p-low pr-targeting-2.0 This PR is targeting the 2.0 branch pr-waiting-on-author
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Rustfmt puts single-line comment after wrong import when reordering imports
3 participants