Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

nazarhussain
Copy link
Contributor

Summary

Add a configuration for the formatter sortMode with either alphabetical or natural (default) options. This sorting mode applies to the import sorting, sorting keys and sorting attributes.

Motivation

Not all projects and teams have same preferences when it comes to code formatting, and it's much inclusive approach to give them option rather than enforcing one format. In addition:

  • Natural sorting seems good mostly when there are numbers involved in the names of literals. My personal observation is that's not a big use case among many projects and codebases.
  • When it comes to projects which have mix of types and code, mostly the types follow PascalCase and others follow either camelCase or CAPITAL_CASE, in that format alphabetical sorting seems more readable.

Test Plan

Added the spec tests

NOTE:

  • I am not a Rust guru, so there may be some points of improvements for performance.
  • I wanted to keep the sorting mode singletone and cloned for different file formats but could not find better way in current code structure.

Copy link

changeset-bot bot commented Jun 23, 2025

🦋 Changeset detected

Latest commit: e2e4556

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 14 packages
Name Type
@biomejs/biome Minor
@biomejs/cli-win32-x64 Minor
@biomejs/cli-win32-arm64 Minor
@biomejs/cli-darwin-x64 Minor
@biomejs/cli-darwin-arm64 Minor
@biomejs/cli-linux-x64 Minor
@biomejs/cli-linux-arm64 Minor
@biomejs/cli-linux-x64-musl Minor
@biomejs/cli-linux-arm64-musl Minor
@biomejs/wasm-web Minor
@biomejs/wasm-bundler Minor
@biomejs/wasm-nodejs Minor
@biomejs/backend-jsonrpc Patch
@biomejs/js-api Major

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@github-actions github-actions bot added A-Project Area: project A-Linter Area: linter A-Formatter Area: formatter L-JavaScript Language: JavaScript and super languages labels Jun 23, 2025
@dyc3
Copy link
Contributor

dyc3 commented Jun 23, 2025

Thanks for the PR! The scope of this PR is pretty big. IMO, I would prefer if a discussion was opened first so that we could gather community feedback on the feature to see if there's enough demand for it, and to agree and align on scope.

I'm personally on the fence about how useful this would realistically be -- the value add feels negligible.

Implementation wise, it's a bit unusual to add a formatter option where it's mostly used in assists. We have a pretty high bar for adding formatter options. It would make a lot more sense (at least for now) to have the option be per-rule.

@nazarhussain
Copy link
Contributor Author

I'm personally on the fence about how useful this would realistically be -- the value add feels negligible.

I feel that value addition is particularly based on the nature of project. The moment I upgrade Biome, it was a clear that my team will not go along this kind of import sorting. And there is also a demand building up from the community #6122, and from that you can see different impact of selecting sorting logic. If you feel I can open open discussion in Github/Discord anywhere you want to gather more feedback.

Implementation wise, it's a bit unusual to add a formatter option where it's mostly used in assists.

Yes, I started PR earlier by setting up option per assist, but later observed that this is actually a formatter option like indent_style, attribute_position and bracket_spacing etc this seems more natural that sort_mode come under formatter. If you prefer otherwise, I can move those to per assist option.

@arendjr
Copy link
Contributor

arendjr commented Jun 24, 2025

Agreed a little more discussion might've helped, but it seems indeed #6122 makes a good case for why we want this functionality.

Also agreed that the setting should be an assist option rather than a formatter option though. The formatter itself doesn't apply sorting/ordering at all, and having the option there would give the impression that it does, which I think is a bit misleading. And who knows, maybe some people want different orderings for keys than they want for imports, for instance, so per assist makes it more flexible too. I think if you make that change indeed, we can accept this PR.

@Conaclos
Copy link
Member

Conaclos commented Jun 24, 2025

I am not sure to see the relation between sort_mode and #6122.
To me, #6122 suggests adding a way to customize the order of property names, allowing you to place name before author in files such as package.json.
There is no request to switch to alphabetical order instead of natural order.

The natural order provided by Biome is really close to an alphabetical order. The main difference is number sorting.
It could be nice to open a discussion and explain why it is an issue in your case.

@matthewkeil
Copy link
Contributor

Signaling support for this feature 🚀

@github-actions github-actions bot added L-CSS Language: CSS L-JSON Language: JSON and super languages A-Project Area: project and removed A-Project Area: project A-Formatter Area: formatter labels Jun 25, 2025
@nazarhussain nazarhussain force-pushed the nh/import-sort-config branch 3 times, most recently from 9a41999 to 89f8af5 Compare June 26, 2025 15:29
@nazarhussain
Copy link
Contributor Author

@arendjr I had updated the PR with options specific to the assists rules. And kept schema configuration in a way that it not breaking any change in previous release.

Though having one last error now.

thread 'specs::source::use_sorted_keys::sorted_alphabetical_js' panicked at /biome/crates/biome_analyze/src/options.rs:23:9:
assertion `left == right` failed
  left: TypeId(0xa0d302f587c7b29fa87ec27d3ecb9043)
 right: TypeId(0xca5b249dab56609f7f688ff4e4b80f35)
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

---- specs::source::use_sorted_keys::sorted_natural_js stdout ----

thread 'specs::source::use_sorted_keys::sorted_natural_js' panicked at /biome/crates/biome_analyze/src/options.rs:23:9:
assertion `left == right` failed
  left: TypeId(0xa0d302f587c7b29fa87ec27d3ecb9043)
 right: TypeId(0xca5b249dab56609f7f688ff4e4b80f35)


failures:
    specs::source::use_sorted_keys::sorted_alphabetical_js
    specs::source::use_sorted_keys::sorted_natural_js

test result: FAILED. 1472 passed; 2 failed; 0 ignored; 0 measured; 14 filtered out; finished in 3.36s

And this is because in configuration crate we are picking useSortedKeys attributes from JSON analyzer package. And with following change we have different Options structs for useSortedKeys in both JS and JSON analyzer package.

pub use_sorted_keys:
Option<RuleAssistConfiguration<biome_json_analyze::options::UseSortedKeys>>,

Please suggest how to fix it? Is there a crate which is usually used in such cases to have shared structs?

@dyc3
Copy link
Contributor

dyc3 commented Jun 26, 2025

For shared options, no not yet. There's an open PR for it #5543

@arendjr
Copy link
Contributor

arendjr commented Jun 29, 2025

So I think for now you will have to duplicate the options. Would that work for you?

@dyc3
Copy link
Contributor

dyc3 commented Jun 29, 2025

I don't think so. The problem comes from there being 2 rules, one for each language, so the name conflicts.

@nazarhussain
Copy link
Contributor Author

I don't think so. The problem comes from there being 2 rules, one for each language, so the name conflicts.

Yes two same name rules for two languages. One for json and other for js, but from configuration exported as json options.

The assert logic want it to be exact same reference of struct. So it works for json but not for js.

Good approach would be to assert if the options are same not the exact object reference.

@dyc3
Copy link
Contributor

dyc3 commented Jun 29, 2025

Well, no, we do want it to be the same struct because we want to keep the options in sync, and that's the easiest way to do that.

Feel free to copy the approach in that PR I linked. I'm on mobile right now so I can't give you links, but IIRC that PR moves options into the common biome_analyze crate.

@nazarhussain nazarhussain force-pushed the nh/import-sort-config branch from 89f8af5 to 2354197 Compare June 30, 2025 15:33
@github-actions github-actions bot added A-Parser Area: parser and removed L-CSS Language: CSS labels Jun 30, 2025
@nazarhussain
Copy link
Contributor Author

I tried to only have methods inside the compareable_token now in reference to the not put the sort_mode into every token, that was redundant and overwhelming for memory.

Please review now @dyc3 @arendjr

Related to the error for cross crate options for similar rules, it seems to have following options for us.

  1. Add simple crate for it in this PR starting with options for useSortedKeys for JS and JSON, and then add more in next PRs for other options.
  2. We already using JSON-Schema for options, so we may implement schema fingerprint hashing, and then compare those. As long options are same, the schema for options will be same and that will work in comparison.

Please review the code and suggest the next steps.

Copy link

codspeed-hq bot commented Jun 30, 2025

CodSpeed Performance Report

Merging #6506 will degrade performances by 61.19%

Comparing nazarhussain:nh/import-sort-config (e2e4556) with next (275cc8b)1

🎉 Hooray! codspeed-rust just leveled up to 3.0.3!

A heads-up, this is a breaking change and it might affect your current performance baseline a bit. But here's the exciting part - it's packed with new, cool features and promises improved result stability 🥳!
Curious about what's new? Visit our releases page to delve into all the awesome details about this new version.

Summary

⚡ 1 improvements
❌ 3 regressions
✅ 110 untouched benchmarks
🆕 1 new benchmarks

⚠️ Please fix the performance issues or acknowledge them on CodSpeed.

Benchmarks breakdown

Benchmark BASE HEAD Change
js_analyzer[index_3894593175024091846.js] 49.4 ms 52.9 ms -6.61%
js_analyzer[parser_13571644119461115204.ts] 79.4 ms 85.5 ms -7.11%
🆕 module_graph[@next/font/google/index.d.ts] N/A 290.3 ms N/A
deserialize_from_json_str[package.json] 1,038.3 µs 930.8 µs +11.55%
deserialize_from_json_str[tsconfig.json] 218 µs 561.8 µs -61.19%

Footnotes

  1. No successful run was found on next (0d91423) during the generation of this report, so f00af73 was used instead as the comparison base. There might be some changes unrelated to this pull request in this report.

@arendjr
Copy link
Contributor

arendjr commented Jun 30, 2025

It seems #5543 is almost ready to be merged. Is it okay we keep this on hold until it is ready? You'll probably need a rebase after that, but it should solve the issues with the codegen/schema.

@nazarhussain
Copy link
Contributor Author

@arendjr I had fixed the lint/fmt issues and also added the changeset. For the website update, is it possible to open a PR there now or have to wait for this one to be merged first? The instructions are not that much clear for understanding.

Copy link
Contributor

@arendjr arendjr left a comment

Choose a reason for hiding this comment

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

Great! Yes, you can create the PR there now, I'll clarify the docs.

Co-authored-by: Arend van Beelen jr. <[email protected]>
@arendjr
Copy link
Contributor

arendjr commented Jul 8, 2025

Wait, I may be leading you astray with the suggestion to open a PR against the website: Maybe the docs should simply be updated by adding docs to UseSortedAttributesOptions and similar structs in this PR. Once you do that, I'm not sure what remains to be updated on the website itself, but that's something @ematipico should be able to tell you.

@ematipico
Copy link
Member

Yeah, apologise for the lack of proper directions regarding this. I will make sure to address it in the coming days.

For docs, even if they are shared, we must document them in the rule/action itself.

When you document the option like this

struct UseSortedAttributesOptions {
   // i am documentation
	foo_bar: bool
}

The documentation will only appear as a description of the schema, so we should keep it generic and it's applicable to all rules that will consume that option.

However, we also want to update the docs of the rule/action too so we can create an example:

## Options

The action accepts the following options

### `nameOfTheOption`

This option is amazing and does this. In the following example, the options makes the code look differently beauftilf

```json,options
{
	"options" {
		"nameOfTheOption": true
	}
}
```

```js,use_options,expect_diagnostics
function fn() {}
```

Of course, the code block has to change to meet the expectations of the option. In this case, we need to use expect_diagnostics so users can see how the option affects the code.

@nazarhussain
Copy link
Contributor Author

@ematipico I added doc comments with updated options. Please review and suggest if there is nay change needed.

@ematipico ematipico changed the base branch from main to next July 9, 2025 05:56
@@ -618,6 +618,23 @@ declare_source_rule! {
/// }
/// ```
///
/// ## Options
Copy link
Member

Choose a reason for hiding this comment

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

It seems my suggestion was too literal 😅 as you can see, this action uses its own format for documenting the options, I'd we should stick with it.

Suggested change
/// ## Options
/// ## Change the sorting of the identifiers

Comment on lines 622 to 627
/// This actions accepts following options
///
/// ### `groups`
/// The usage of `groups` is explained in detail above.
///
/// ### `identifierOrder`
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
/// This actions accepts following options
///
/// ### `groups`
/// The usage of `groups` is explained in detail above.
///
/// ### `identifierOrder`

/// }
/// }
/// ```
///
Copy link
Member

Choose a reason for hiding this comment

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

Here, you want to add a snippet that uses the options you defined at line 631. Create a js code block:

```js,use_options,expect_diagnostic
// code here
```

Of course, you want to use a code that shows how the natural order is applied

/// }
/// }
/// ```
///
Copy link
Member

Choose a reason for hiding this comment

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

Here too, we want to add a snippet that uses the options. Please refer to our contribution guide https://github.com/biomejs/biome/blob/main/crates/biome_analyze/CONTRIBUTING.md#using-rule-options

/// }
/// }
/// ```
///
Copy link
Member

Choose a reason for hiding this comment

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

Here too, let's add a snippet

@nazarhussain
Copy link
Contributor Author

@ematipico Thanks for your feedback. There were no invalid/valid cases for the assists I believe so I added examples which shows what diagnostic after sorting.

Let me know if that's good or suggest any changes.

@nazarhussain nazarhussain requested a review from ematipico July 9, 2025 11:28
@ematipico
Copy link
Member

@nazarhussain the PR is still failing, can you please address it? It seems that the code blocks you added in the docs have syntax errors.

@nazarhussain
Copy link
Contributor Author

Seems issue happens from base branch, as lint passing for me locally.

cargo lint
....
....
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 25.51s

I will try to rebase or update the branch.

@nazarhussain
Copy link
Contributor Author

@nazarhussain the PR is still failing, can you please address it? It seems that the code blocks you added in the docs have syntax errors.

@ematipico Please rerun the CI and re-review this PR.

@ematipico ematipico added this to the Biome v2.2 milestone Jul 21, 2025
@ematipico ematipico merged commit 90c5d6b into biomejs:next Jul 22, 2025
27 of 28 checks passed
ematipico added a commit that referenced this pull request Aug 12, 2025
…utes (#6506)

Co-authored-by: Arend van Beelen jr. <[email protected]>

Co-authored-by: dyc3 <[email protected]>
Co-authored-by: arendjr <[email protected]>
Co-authored-by: Conaclos <[email protected]>
Co-authored-by: matthewkeil <[email protected]>
Co-authored-by: ematipico <[email protected]>
@github-actions github-actions bot mentioned this pull request Aug 13, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-Linter Area: linter L-JavaScript Language: JavaScript and super languages L-JSON Language: JSON and super languages
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants