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

feat(biome_js_analyze): add useSortedKeys assist rule #5079

Open
wants to merge 6 commits into
base: main
Choose a base branch
from

Conversation

r1tsuu
Copy link

@r1tsuu r1tsuu commented Feb 10, 2025

Summary

Add a new assist rule - useSortedKeys which enforces ordering of a JS object properties.
This rule will consider spread/calculated keys e.g [k]: 1 as non-sortable.
Instead, whenever it encounters a non-sortable key, it will sort all the
previous sortable keys up until the nearest non-sortable key, if one exist.
This prevents breaking the override of certain keys using spread keys.

Source: https://perfectionist.dev/rules/sort-objects

// Base
// from
const obj = {
  b: 1,
  a: 1,
  ...g,
  ba: 2,
  ab: 1,
  set aab(v) {
    this._aab = v;
  },
  [getProp()]: 2,
  aba: 2,
  abc: 3,
  abb: 3,
  get aaa() {
    return "";
  },
};
// to
const obj = {
  a: 1,
  b: 1,
  ...g,
  set aab(v) {
    this._aab = v;
  },
  ab: 1,
  ba: 2,
  [getProp()]: 2,
  get aaa() {
    return "";
  },
  aba: 2,
  abb: 3,
  abc: 3,
};

How it is implemented

The run method of the rule queries JSObjectMemberList and collects all the members to Vec<Vec<ObjectMember>> state which is a list of groups, each group is separated by a spread or a computed key. Then, in the action we check if the current state is sorted (Ord was implemented for ObjectMember using natord for natural ordering) and if not - iterate through sorted - non sorted pairs (with zip) and replace the nodes.

The logic is very similar to the existing useSortedAttributes rule for JSX properties.

Test plan

Includes 2 snapshot tests - sorted and unsorted.

@github-actions github-actions bot added A-Project Area: project A-Linter Area: linter L-JavaScript Language: JavaScript and super languages labels Feb 10, 2025
Comment on lines 17 to 25
#[derive(Debug, Default, Clone, PartialEq, Eq, Serialize, Deserialize, Deserializable)]
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
#[serde(rename_all = "camelCase", deny_unknown_fields, default)]
pub struct UseSortedPropertiesOptions {
/// Partition the object properties by a newline.
pub partion_by_new_line: bool,
/// Partition the object properties by a comment.
pub partion_by_comment: bool,
}
Copy link
Contributor

Choose a reason for hiding this comment

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

As a general rule of thumb, we don't implement options for new rules on the first iteration to avoid unnecessary complexity. Lets leave these out for now.

Copy link

codspeed-hq bot commented Feb 10, 2025

CodSpeed Performance Report

Merging #5079 will not alter performance

Comparing r1tsuu:feat/useSortProperties (c3ebe18) with main (9280cba)

Summary

✅ 94 untouched benchmarks

@r1tsuu r1tsuu force-pushed the feat/useSortProperties branch from 16753e7 to 1f56f09 Compare February 11, 2025 06:34
Copy link
Member

@ematipico ematipico left a comment

Choose a reason for hiding this comment

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

Blocking because this PR should go against next and match the new contribution guidelines. The changeset is missing

@r1tsuu r1tsuu changed the base branch from main to next February 11, 2025 11:13
@r1tsuu r1tsuu force-pushed the feat/useSortProperties branch from 5b133c8 to 3770bfd Compare February 11, 2025 11:14
@r1tsuu r1tsuu changed the title feat(biome_js_analyze): useSortedProperties feat(biome_js_analyze): add useSortedObjectProperties assist rule Feb 11, 2025
@r1tsuu
Copy link
Author

r1tsuu commented Feb 11, 2025

I updated the PR to be based on the next branch and added the changeset. Also renamed the rule as I noticed that useSortedProperties already exists for CSS.

@dyc3 dyc3 changed the title feat(biome_js_analyze): add useSortedObjectProperties assist rule feat(biome_js_analyze): add useSortedProperties assist rule Feb 11, 2025
@dyc3 dyc3 changed the title feat(biome_js_analyze): add useSortedProperties assist rule feat(biome_js_analyze): add useSortedObjectProperties assist rule Feb 11, 2025
@ematipico
Copy link
Member

Also renamed the rule as I noticed that useSortedProperties already exists for CSS.

Biome linter is particular, and the same rule can be applied to multiple languages. If the intent of the rule is the same, we should implement the same rule for new languages.

Also, there's already a rule called useSortedKeys in the JSON language, which does exactly the same for this rule, hence I believe they should share the same name.

@r1tsuu
Copy link
Author

r1tsuu commented Feb 11, 2025

Also renamed the rule as I noticed that useSortedProperties already exists for CSS.

Biome linter is particular, and the same rule can be applied to multiple languages. If the intent of the rule is the same, we should implement the same rule for new languages.

Also, there's already a rule called useSortedKeys in the JSON language, which does exactly the same for this rule, hence I believe they should share the same name.

It makes sense, I tried to rename to useSortedKeys and It causes some overlap for the codegen because they, although are for different languages share the same namespace for the config:

"Source": {
"description": "A list of rules that belong to this group",
"type": "object",
"properties": {
"organizeImports": {
"description": "Provides a whole-source code action to sort the imports in the file using import groups and natural ordering.",
"anyOf": [
{ "$ref": "#/definitions/RuleAssistConfiguration_for_Options" },
{ "type": "null" }
]
},
"recommended": {
"description": "It enables the recommended rules for this group",
"type": ["boolean", "null"]
},
"useSortedAttributes": {
"description": "Enforce attribute sorting in JSX elements.",
"anyOf": [
{ "$ref": "#/definitions/RuleAssistConfiguration_for_Null" },
{ "type": "null" }
]
},
"useSortedKeys": {
"description": "Sorts the keys of a JSON object in natural order",
"anyOf": [
{ "$ref": "#/definitions/RuleAssistConfiguration_for_Null" },
{ "type": "null" }
]
},
"useSortedProperties": {
"description": "Enforce ordering of CSS properties and nested rules.",
"anyOf": [
{ "$ref": "#/definitions/RuleAssistConfiguration_for_Null" },
{ "type": "null" }
]
}
},
"additionalProperties": false
, the same in crates/biome_configuration/src/analyzer/assist/actions.rs. The same for useSortedProperties, it already exists here

@dyc3
Copy link
Contributor

dyc3 commented Feb 11, 2025

That should be fine. Is the codegen throwing any errors for you? It works fine on my machine.

@r1tsuu
Copy link
Author

r1tsuu commented Feb 11, 2025

The current commit is fine, I was about to rename that property from useSortedObjectProperties to useSortedKeys and it overlaps with the other property that has the same name in the source config namespace. Codegen doesn't throw any errors for that case, but then the current useSortedKeys and my useSortedKeys basically share the same description / config type, which probably isn't a desired behavior.

@dyc3
Copy link
Contributor

dyc3 commented Feb 11, 2025

We do this with other rules, like noDuplicateObjectKeys. Users are able have control over which language and files the rule applies to. So it's OK to have the rule names overlap.

@github-actions github-actions bot removed the A-Project Area: project label Feb 11, 2025
@r1tsuu r1tsuu changed the title feat(biome_js_analyze): add useSortedObjectProperties assist rule feat(biome_js_analyze): add useSortedKeys assist rule Feb 11, 2025
@dyc3 dyc3 requested a review from ematipico February 11, 2025 22:56
@ematipico ematipico deleted the branch biomejs:main February 12, 2025 11:41
@ematipico ematipico closed this Feb 12, 2025
@ematipico ematipico reopened this Feb 12, 2025
@ematipico ematipico changed the base branch from next to main February 12, 2025 11:47
@r1tsuu r1tsuu force-pushed the feat/useSortProperties branch from 5562edf to 4c7e012 Compare February 12, 2025 18:06
@r1tsuu r1tsuu force-pushed the feat/useSortProperties branch from 4c7e012 to c3ebe18 Compare February 13, 2025 20:25
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
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants