-
Notifications
You must be signed in to change notification settings - Fork 890
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
Implement version-sort for imports in style_edition
2024
#6284
Conversation
fac7545
to
5f773bb
Compare
also cc @rust-lang/style for awareness as the diff of rustfmt's own imports should demonstrate the effects of the sorting changes |
| (VersionChunk::Str(ca), VersionChunk::Number { source: cb, .. }) | ||
| (VersionChunk::Number { source: ca, .. }, VersionChunk::Str(cb)) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think there's an opportunity to slightly optimize this. When comparing a VersionChunk::Str
with a VersionChunk::Number
I believe that the number will always get sorted first, but I implemented it this way because of this language in the style guide:
To compare two chunks if both are not numeric, compare them by Unicode character lexicographically
I'll add that the style team did review the diff of this PR in our last meeting to observe the changes in action, and the diff (the changes to the rustfmt codebase in 7f0d9a2) aligned with our expectations |
fn parse_numeric_chunk( | ||
&mut self, | ||
mut chars: std::str::CharIndices<'a>, | ||
) -> Option<VersionChunk<'a>> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No changes requested, but sharing an observation that we've got a lot of overlapping code between parse_numeric_chunk
and parse_str_chunk
, with the only difference (other than the final return value) being the couple checks in the while loop.
There's probably an opportunity to DRY that up in the future
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for taking a look. I'll address those merge conflicts and rebase the PR sometime later this week
src/sort.rs
Outdated
let mut input = vec![ | ||
"x87", "Z_YWX", "ZY_WX", "ZYW_X", "ZYWX", "ZYWX_", "v010", "v10", "w005s09t", | ||
"w5s009t", "x64", "x86", "x86_32", "x86_64", "x86_128", "v000", "v00", "v0", "v0s", | ||
"v00t", "v0u", "v001", "v01", "v1", "v009", "v09", "v9", "_ZYWX", "u_zzz", "u8", "u16", | ||
"u32", "u64", "u128", "u256", "ua", "usize", "uz", | ||
]; | ||
let expected = vec![ | ||
"_ZYWX", "Z_YWX", "ZY_WX", "ZYW_X", "ZYWX", "ZYWX_", "u_zzz", "u8", "u16", "u32", | ||
"u64", "u128", "u256", "ua", "usize", "uz", "v000", "v00", "v0", "v0s", "v00t", "v0u", | ||
"v001", "v01", "v1", "v009", "v09", "v9", "v010", "v10", "w005s09t", "w5s009t", "x64", | ||
"x86", "x86_32", "x86_64", "x86_128", "x87", | ||
]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd like to add a test cases that covers the full set of items from the example in the Style Guide, just for thoroughness:
_ZYXW
_abcd
A2
ABCD
Z_YXW
ZY_XW
ZY_XW
ZYXW
ZYXW_
a1
abcd
u_zzz
u8
u16
u32
u64
u128
u256
ua
usize
uz
v000
v00
v0
v0s
v00t
v0u
v001
v01
v1
v009
v09
v9
v010
v10
w005s09t
w5s009t
x64
x86
x86_32
x86_64
x86_128
x87
zyxw
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like the example in the docs changed since I added the test. I've updated it to use the complete example from the guide.
src/sort.rs
Outdated
/// Represents a chunk in the version-sort algorithm | ||
#[derive(Debug, PartialEq, Eq)] | ||
enum VersionChunk<'a> { | ||
/// A singel `_` in an identifier. Underscores are sorted before all other characters. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit but typo
/// A singel `_` in an identifier. Underscores are sorted before all other characters. | |
/// A single `_` in an identifier. Underscores are sorted before all other characters. |
This looks good to me, and I'd be good merging with the extra test case I mentioned inline (it's probably overkill but seems like a good idea to me). Two other things I'll note while I'm thinking about them:
|
oh and I was also wondering if it would be worthwhile to try running this against some codebase that would have idents that would more thoroughly exercise the algorithm (e.g. we don't have the types of numerical, leading zeroes, etc. use cases the algorithm prescribes within the rustfmt source) |
As the algorithm is implemented in this PR it only really applies to identifiers, which shouldn't be allowed to contain spaces. For that reason I didn't worry too much about space handling, and I don't think there would be scenarios where we'd need to worry about sorting things with spaces, but correct me if I'm wrong. When it comes to follow up PRs I was mostly talking about applying the version sort to other AST nodes. I know #3764 also applied sorting to associated items, but I wasn't sure if there were others that we needed to consider as well.
For now I've updated the unit test with the example from the style guide, and I've also added an idempotence test in a0f80f3.
I think this could be worthwhile. I Tried running a Diff-Check when passing |
Yeah that was the concern we had in our style meeting as well, that blasting it against a large, general corpus of code would be highly noisy. No need to block on this, but maybe we can get a call to action out there in some way, as it would be nice to find a good codebase that would have minimal noise |
The algorithm is described in the [style guide] and was introduced in `r-l/rust 115046`. [style guide]: https://doc.rust-lang.org/nightly/style-guide/#sorting
The version-sort algorithm makes changes to the sort order of imports, and we're updating them here for the self tests.
This was one of the original issues filed against rustfmt that discussed using a natural sort order instead of a lexicographical order. At the time it was closed, but now that we're supporting version-sorting in `style_edition=2024` I thought it would be good to add a test case.
a0f80f3
to
4192118
Compare
Agreed, I think that was included to cover bases algorithmically This looks good to me, i've done a rebase so we can proceed with a merge. If you see CI go green before me then feel free to merge, otherwise I'll do it later today |
Bump stage0 to beta-2024-09-22 and rustfmt to nightly-2024-09-22 I'm doing this to apply the changes to version sorting (rust-lang/rustfmt#6284) that have occurred since rustfmt last upgraded (and a few other miscellaneous changes, like changes to expression overflowing: rust-lang/rustfmt#6260). Eagerly updating rustfmt and formatting-the-world will ideally move some of the pressure off of the beta bump which will happen at the beginning of the next release cycle. You can verify this is correct by checking out the changes, reverting the last commit, reapplying them, and diffing the changes: ``` git fetch [email protected]:compiler-errors/rust.git bump git checkout -b bump FETCH_HEAD git reset --hard HEAD~5 ./x.py fmt --all git diff FETCH_HEAD # ignore the changes to stage0, and rustfmt.toml, # and test file changes in rustdoc-js-std, run-make. ``` Or just take my word for it? Up to the reviewer. r? release
The
version-sort
algorithm is described in the sorting section of the style guide and the tracking issue for this in ther-l/rust
repo is rust-lang/rust#123800.This PR implements the algorithm and applies it to import sorting. One of the original PRs that implement this feature was #3764. In that PR the sort order for type aliases was also updated. I decided to keep this PR focused on import sorting, and I plan to open up follow up PRs to address any other sorting that rustfmt needs to apply to conform with the 2024 style_edition.
Given the nature of changing the sort order there were a lot of imports that needed to change in order to pass our self tests. Those changes have all been broken out into their own commit so you can review those changes in isolation from the implementation work. Overall, I've broken the PR into what I think are logical commits and I think it would be best to review the PR one commit at a time.
r? @calebcartwright