From e2839e735fb9098e5610ab0024e645232b688255 Mon Sep 17 00:00:00 2001 From: Sasha <64744993+r1tsuu@users.noreply.github.com> Date: Tue, 11 Feb 2025 13:11:58 +0200 Subject: [PATCH 1/6] feat(biome_js_analyze): add useSortedObjectProperties assist rule --- .changeset/stupid-adults-crash.md | 101 ++++++++++ .../src/analyzer/assist/actions.rs | 23 ++- crates/biome_js_analyze/src/assist/source.rs | 3 +- .../source/use_sorted_object_properties.rs | 185 ++++++++++++++++++ crates/biome_js_analyze/src/options.rs | 1 + .../useSortedObjectProperties/sorted.js | 20 ++ .../useSortedObjectProperties/sorted.js.snap | 28 +++ .../useSortedObjectProperties/unsorted.js | 17 ++ .../unsorted.js.snap | 54 +++++ .../@biomejs/backend-jsonrpc/src/workspace.ts | 4 + .../@biomejs/biome/configuration_schema.json | 7 + 11 files changed, 440 insertions(+), 3 deletions(-) create mode 100644 .changeset/stupid-adults-crash.md create mode 100644 crates/biome_js_analyze/src/assist/source/use_sorted_object_properties.rs create mode 100644 crates/biome_js_analyze/tests/specs/source/useSortedObjectProperties/sorted.js create mode 100644 crates/biome_js_analyze/tests/specs/source/useSortedObjectProperties/sorted.js.snap create mode 100644 crates/biome_js_analyze/tests/specs/source/useSortedObjectProperties/unsorted.js create mode 100644 crates/biome_js_analyze/tests/specs/source/useSortedObjectProperties/unsorted.js.snap diff --git a/.changeset/stupid-adults-crash.md b/.changeset/stupid-adults-crash.md new file mode 100644 index 000000000000..45da0d50499c --- /dev/null +++ b/.changeset/stupid-adults-crash.md @@ -0,0 +1,101 @@ +--- +"@biomejs/biome": minor +--- + +Add a new assist rule - `useSortedObjectProperties` 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 + +```js +// 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, +}; +// partionByNewLine: true +// from +const obj = { + b: 1, + a: 1, + + ba: 2, + ab: 1, + + aba: 2, + abc: 3, + abb: 3, +}; +// to +const obj = { + a: 1, + b: 1, + + ab: 1, + ba: 2, + + aba: 2, + abb: 3, + abc: 3, +}; +// partionByComment: true +// from +const obj = { + b: 1, + a: 1, + // Partion 1 + ba: 2, + ab: 1, + // Partion 2 + aba: 2, + abc: 3, + abb: 3, +}; +// to +const obj = { + a: 1, + b: 1, + // Partion 1 + ab: 1, + ba: 2, + // Partion 2 + aba: 2, + abb: 3, + abc: 3, +}; +``` diff --git a/crates/biome_configuration/src/analyzer/assist/actions.rs b/crates/biome_configuration/src/analyzer/assist/actions.rs index 08da0f94a2b5..bc1dad6f3a4b 100644 --- a/crates/biome_configuration/src/analyzer/assist/actions.rs +++ b/crates/biome_configuration/src/analyzer/assist/actions.rs @@ -131,6 +131,10 @@ pub struct Source { #[serde(skip_serializing_if = "Option::is_none")] pub use_sorted_keys: Option>, + #[doc = "Enforce ordering of JS objects properties."] + #[serde(skip_serializing_if = "Option::is_none")] + pub use_sorted_object_properties: + Option>, #[doc = "Enforce ordering of CSS properties and nested rules."] #[serde(skip_serializing_if = "Option::is_none")] pub use_sorted_properties: @@ -142,6 +146,7 @@ impl Source { "organizeImports", "useSortedAttributes", "useSortedKeys", + "useSortedObjectProperties", "useSortedProperties", ]; const RECOMMENDED_RULES_AS_FILTERS: &'static [RuleFilter<'static>] = @@ -173,11 +178,16 @@ impl Source { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[2])); } } - if let Some(rule) = self.use_sorted_properties.as_ref() { + if let Some(rule) = self.use_sorted_object_properties.as_ref() { if rule.is_enabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[3])); } } + if let Some(rule) = self.use_sorted_properties.as_ref() { + if rule.is_enabled() { + index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[4])); + } + } index_set } pub(crate) fn get_disabled_rules(&self) -> FxHashSet> { @@ -197,11 +207,16 @@ impl Source { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[2])); } } - if let Some(rule) = self.use_sorted_properties.as_ref() { + if let Some(rule) = self.use_sorted_object_properties.as_ref() { if rule.is_disabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[3])); } } + if let Some(rule) = self.use_sorted_properties.as_ref() { + if rule.is_disabled() { + index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[4])); + } + } index_set } #[doc = r" Checks if, given a rule name, matches one of the rules contained in this category"] @@ -235,6 +250,10 @@ impl Source { .use_sorted_keys .as_ref() .map(|conf| (conf.level(), conf.get_options())), + "useSortedObjectProperties" => self + .use_sorted_object_properties + .as_ref() + .map(|conf| (conf.level(), conf.get_options())), "useSortedProperties" => self .use_sorted_properties .as_ref() diff --git a/crates/biome_js_analyze/src/assist/source.rs b/crates/biome_js_analyze/src/assist/source.rs index ca871e3b5164..2ae96be8e36a 100644 --- a/crates/biome_js_analyze/src/assist/source.rs +++ b/crates/biome_js_analyze/src/assist/source.rs @@ -5,4 +5,5 @@ use biome_analyze::declare_assist_group; pub mod organize_imports; pub mod use_sorted_attributes; -declare_assist_group! { pub Source { name : "source" , rules : [self :: organize_imports :: OrganizeImports , self :: use_sorted_attributes :: UseSortedAttributes ,] } } +pub mod use_sorted_object_properties; +declare_assist_group! { pub Source { name : "source" , rules : [self :: organize_imports :: OrganizeImports , self :: use_sorted_attributes :: UseSortedAttributes , self :: use_sorted_object_properties :: UseSortedObjectProperties ,] } } diff --git a/crates/biome_js_analyze/src/assist/source/use_sorted_object_properties.rs b/crates/biome_js_analyze/src/assist/source/use_sorted_object_properties.rs new file mode 100644 index 000000000000..710ed5be57d1 --- /dev/null +++ b/crates/biome_js_analyze/src/assist/source/use_sorted_object_properties.rs @@ -0,0 +1,185 @@ +use std::borrow::Cow; +use std::cmp::Ordering; + +use biome_analyze::{context::RuleContext, declare_source_rule, Ast, Rule, RuleAction}; +use biome_console::markup; +use biome_diagnostics::Applicability; +use biome_js_syntax::{AnyJsObjectMember, AnyJsObjectMemberName, JsObjectMemberList}; +use biome_rowan::{AstSeparatedList, BatchMutationExt, SyntaxResult}; + +use crate::JsRuleAction; + +declare_source_rule! { + /// Enforce ordering of a JS object properties. + /// + /// This rule checks if keys of the object are sorted in a consistent way. + /// Keys are sorted in a natural order. + /// 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 + /// + /// ## Examples + /// + /// ```js,expect_diff + /// { + /// x: 1, + /// a: 2, + /// }; + /// ``` + /// + /// ```js,expect_diff + /// { + /// x: 1, + /// ...f, + /// y: 4, + /// a: 2, + /// [calculated()]: true, + /// b: 3, + /// a: 1, + /// }; + /// ``` + /// + /// ```js,expect_diff + /// { + /// get aab() { + /// return this._aab; + /// }, + /// set aac(v) { + /// this._aac = v; + /// }, + /// w: 1, + /// x: 1, + /// ...g, + /// get aaa() { + /// return ""; + /// }, + /// u: 1, + /// v: 1, + /// [getProp()]: 2, + /// o: 1, + /// p: 1, + /// q: 1, + /// } + /// ``` + pub UseSortedObjectProperties { + version: "1.0.0", + name: "useSortedObjectProperties", + language: "js", + recommended: false, + } +} + +impl Rule for UseSortedObjectProperties { + type Query = Ast; + type State = Vec>; + type Signals = Option; + type Options = (); + + fn run(ctx: &RuleContext) -> Self::Signals { + let mut members = vec![]; + let mut groups = vec![]; + + let get_name = + |name: SyntaxResult| Some(name.ok()?.name()?.text().to_string()); + + for element in ctx.query().elements() { + if let Ok(element) = element.node() { + match element { + AnyJsObjectMember::JsSpread(_) | AnyJsObjectMember::JsBogusMember(_) => { + // Keep the spread order because it's not safe to change order of it. + // Logic here is similar to /crates/biome_js_analyze/src/assists/source/use_sorted_attributes.rs + groups.push(members.clone()); + members.clear(); + members.push(ObjectMember::new(element.clone(), None)); + } + AnyJsObjectMember::JsPropertyObjectMember(member) => { + members.push(ObjectMember::new(element.clone(), get_name(member.name()))); + } + AnyJsObjectMember::JsGetterObjectMember(member) => { + members.push(ObjectMember::new(element.clone(), get_name(member.name()))); + } + AnyJsObjectMember::JsSetterObjectMember(member) => { + members.push(ObjectMember::new(element.clone(), get_name(member.name()))); + } + AnyJsObjectMember::JsMethodObjectMember(member) => { + members.push(ObjectMember::new(element.clone(), get_name(member.name()))); + } + AnyJsObjectMember::JsShorthandPropertyObjectMember(member) => { + let name = member + .name() + .ok() + .map(|name| Some(name.name().ok()?.text().to_string())) + .unwrap_or_default(); + + members.push(ObjectMember::new(element.clone(), name)); + } + } + } + } + + if !members.is_empty() { + groups.push(members); + } + + Some(groups) + } + + fn action(ctx: &RuleContext, state: &Self::State) -> Option { + let mut sorted_state = state.clone(); + + for group in sorted_state.iter_mut() { + group.sort(); + } + + if sorted_state == *state { + return None; + } + + let mut mutation = ctx.root().begin(); + + for (unsorted, sorted) in state.iter().flatten().zip(sorted_state.iter().flatten()) { + mutation.replace_node(unsorted.member.clone(), sorted.member.clone()); + } + + Some(RuleAction::new( + rule_action_category!(), + Applicability::Always, + markup! { "Sort the object properties." }, + mutation, + )) + } +} + +#[derive(PartialEq, Eq, Clone)] +pub struct ObjectMember { + member: AnyJsObjectMember, + name: Option, +} + +impl ObjectMember { + fn new(member: AnyJsObjectMember, name: Option) -> Self { + ObjectMember { member, name } + } +} + +impl Ord for ObjectMember { + fn cmp(&self, other: &Self) -> Ordering { + // If some doesn't have a name (e.g spread/calculated property) - keep the order. + let (Some(self_name), Some(other_name)) = (&self.name, &other.name) else { + return Ordering::Equal; + }; + + natord::compare(self_name, other_name) + } +} + +impl PartialOrd for ObjectMember { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} diff --git a/crates/biome_js_analyze/src/options.rs b/crates/biome_js_analyze/src/options.rs index daac061085a7..bcdb1cf0af12 100644 --- a/crates/biome_js_analyze/src/options.rs +++ b/crates/biome_js_analyze/src/options.rs @@ -413,6 +413,7 @@ pub type UseSortedAttributes = ::Options; pub type UseSortedClasses = ::Options; +pub type UseSortedObjectProperties = < assist :: source :: use_sorted_object_properties :: UseSortedObjectProperties as biome_analyze :: Rule > :: Options ; pub type UseStrictMode = ::Options; pub type UseTemplate = ::Options; diff --git a/crates/biome_js_analyze/tests/specs/source/useSortedObjectProperties/sorted.js b/crates/biome_js_analyze/tests/specs/source/useSortedObjectProperties/sorted.js new file mode 100644 index 000000000000..68c1963e3154 --- /dev/null +++ b/crates/biome_js_analyze/tests/specs/source/useSortedObjectProperties/sorted.js @@ -0,0 +1,20 @@ +const obj = { + get aab() { + return this._aab; + }, + set aac(v) { + this._aac = v; + }, + w: 1, + x: 1, + ...g, + get aaa() { + return ""; + }, + u: 1, + v: 1, + [getProp()]: 2, + o: 1, + p: 1, + q: 1, +}; diff --git a/crates/biome_js_analyze/tests/specs/source/useSortedObjectProperties/sorted.js.snap b/crates/biome_js_analyze/tests/specs/source/useSortedObjectProperties/sorted.js.snap new file mode 100644 index 000000000000..e152b750107f --- /dev/null +++ b/crates/biome_js_analyze/tests/specs/source/useSortedObjectProperties/sorted.js.snap @@ -0,0 +1,28 @@ +--- +source: crates/biome_js_analyze/tests/spec_tests.rs +expression: sorted.js +--- +# Input +```js +const obj = { + get aab() { + return this._aab; + }, + set aac(v) { + this._aac = v; + }, + w: 1, + x: 1, + ...g, + get aaa() { + return ""; + }, + u: 1, + v: 1, + [getProp()]: 2, + o: 1, + p: 1, + q: 1, +}; + +``` diff --git a/crates/biome_js_analyze/tests/specs/source/useSortedObjectProperties/unsorted.js b/crates/biome_js_analyze/tests/specs/source/useSortedObjectProperties/unsorted.js new file mode 100644 index 000000000000..ff5a9d39af29 --- /dev/null +++ b/crates/biome_js_analyze/tests/specs/source/useSortedObjectProperties/unsorted.js @@ -0,0 +1,17 @@ +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 ""; + }, +}; diff --git a/crates/biome_js_analyze/tests/specs/source/useSortedObjectProperties/unsorted.js.snap b/crates/biome_js_analyze/tests/specs/source/useSortedObjectProperties/unsorted.js.snap new file mode 100644 index 000000000000..55e7d183f256 --- /dev/null +++ b/crates/biome_js_analyze/tests/specs/source/useSortedObjectProperties/unsorted.js.snap @@ -0,0 +1,54 @@ +--- +source: crates/biome_js_analyze/tests/spec_tests.rs +expression: unsorted.js +--- +# Input +```js +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 ""; + }, +}; + +``` + +# Actions +```diff +@@ -1,17 +1,17 @@ + const obj = { ++ a: 1, + b: 1, +- a: 1, + ...g, +- ba: 2, +- ab: 1, + set aab(v) { + this._aab = v; + }, ++ ab: 1, ++ ba: 2, + [getProp()]: 2, +- aba: 2, +- abc: 3, +- abb: 3, + get aaa() { + return ""; + }, ++ aba: 2, ++ abb: 3, ++ abc: 3, + }; + +``` diff --git a/packages/@biomejs/backend-jsonrpc/src/workspace.ts b/packages/@biomejs/backend-jsonrpc/src/workspace.ts index a3231211468d..c398a42c6eb8 100644 --- a/packages/@biomejs/backend-jsonrpc/src/workspace.ts +++ b/packages/@biomejs/backend-jsonrpc/src/workspace.ts @@ -839,6 +839,10 @@ export interface Source { * Sorts the keys of a JSON object in natural order */ useSortedKeys?: RuleAssistConfiguration_for_Null; + /** + * Enforce ordering of JS objects properties. + */ + useSortedObjectProperties?: RuleAssistConfiguration_for_Null; /** * Enforce ordering of CSS properties and nested rules. */ diff --git a/packages/@biomejs/biome/configuration_schema.json b/packages/@biomejs/biome/configuration_schema.json index 6f5c60349c68..ab04bca5d2f7 100644 --- a/packages/@biomejs/biome/configuration_schema.json +++ b/packages/@biomejs/biome/configuration_schema.json @@ -3943,6 +3943,13 @@ { "type": "null" } ] }, + "useSortedObjectProperties": { + "description": "Enforce ordering of JS objects properties.", + "anyOf": [ + { "$ref": "#/definitions/RuleAssistConfiguration_for_Null" }, + { "type": "null" } + ] + }, "useSortedProperties": { "description": "Enforce ordering of CSS properties and nested rules.", "anyOf": [ From 408a0cb970043138fd2d5671aa69960f1229a0ed Mon Sep 17 00:00:00 2001 From: Sasha <64744993+r1tsuu@users.noreply.github.com> Date: Tue, 11 Feb 2025 13:25:04 +0200 Subject: [PATCH 2/6] chore: remove partion by new line and partion by comment from the changeset --- .changeset/stupid-adults-crash.md | 50 ------------------------------- 1 file changed, 50 deletions(-) diff --git a/.changeset/stupid-adults-crash.md b/.changeset/stupid-adults-crash.md index 45da0d50499c..068e6efdabc4 100644 --- a/.changeset/stupid-adults-crash.md +++ b/.changeset/stupid-adults-crash.md @@ -48,54 +48,4 @@ const obj = { abb: 3, abc: 3, }; -// partionByNewLine: true -// from -const obj = { - b: 1, - a: 1, - - ba: 2, - ab: 1, - - aba: 2, - abc: 3, - abb: 3, -}; -// to -const obj = { - a: 1, - b: 1, - - ab: 1, - ba: 2, - - aba: 2, - abb: 3, - abc: 3, -}; -// partionByComment: true -// from -const obj = { - b: 1, - a: 1, - // Partion 1 - ba: 2, - ab: 1, - // Partion 2 - aba: 2, - abc: 3, - abb: 3, -}; -// to -const obj = { - a: 1, - b: 1, - // Partion 1 - ab: 1, - ba: 2, - // Partion 2 - aba: 2, - abb: 3, - abc: 3, -}; ``` From 4715fb293952e6c2eaa2c98fe68f5ba37c29a0e9 Mon Sep 17 00:00:00 2001 From: Sasha <64744993+r1tsuu@users.noreply.github.com> Date: Tue, 11 Feb 2025 17:18:55 +0200 Subject: [PATCH 3/6] chore: update rule version to `"next"` Co-authored-by: Carson McManus --- .../src/assist/source/use_sorted_object_properties.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/biome_js_analyze/src/assist/source/use_sorted_object_properties.rs b/crates/biome_js_analyze/src/assist/source/use_sorted_object_properties.rs index 710ed5be57d1..7627549f0d7f 100644 --- a/crates/biome_js_analyze/src/assist/source/use_sorted_object_properties.rs +++ b/crates/biome_js_analyze/src/assist/source/use_sorted_object_properties.rs @@ -67,7 +67,7 @@ declare_source_rule! { /// } /// ``` pub UseSortedObjectProperties { - version: "1.0.0", + version: "next", name: "useSortedObjectProperties", language: "js", recommended: false, From 5529910a2f87e75cccd459093c2d7cabc7f2373c Mon Sep 17 00:00:00 2001 From: Sasha <64744993+r1tsuu@users.noreply.github.com> Date: Tue, 11 Feb 2025 17:22:34 +0200 Subject: [PATCH 4/6] chore: re-codegen --- crates/biome_configuration/src/analyzer/assist/actions.rs | 2 +- packages/@biomejs/backend-jsonrpc/src/workspace.ts | 2 +- packages/@biomejs/biome/configuration_schema.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/biome_configuration/src/analyzer/assist/actions.rs b/crates/biome_configuration/src/analyzer/assist/actions.rs index bc1dad6f3a4b..2c3fd75bb82b 100644 --- a/crates/biome_configuration/src/analyzer/assist/actions.rs +++ b/crates/biome_configuration/src/analyzer/assist/actions.rs @@ -131,7 +131,7 @@ pub struct Source { #[serde(skip_serializing_if = "Option::is_none")] pub use_sorted_keys: Option>, - #[doc = "Enforce ordering of JS objects properties."] + #[doc = "Enforce ordering of a JS object properties."] #[serde(skip_serializing_if = "Option::is_none")] pub use_sorted_object_properties: Option>, diff --git a/packages/@biomejs/backend-jsonrpc/src/workspace.ts b/packages/@biomejs/backend-jsonrpc/src/workspace.ts index c398a42c6eb8..1413e627e9cb 100644 --- a/packages/@biomejs/backend-jsonrpc/src/workspace.ts +++ b/packages/@biomejs/backend-jsonrpc/src/workspace.ts @@ -840,7 +840,7 @@ export interface Source { */ useSortedKeys?: RuleAssistConfiguration_for_Null; /** - * Enforce ordering of JS objects properties. + * Enforce ordering of a JS object properties. */ useSortedObjectProperties?: RuleAssistConfiguration_for_Null; /** diff --git a/packages/@biomejs/biome/configuration_schema.json b/packages/@biomejs/biome/configuration_schema.json index ab04bca5d2f7..ece8df637b2b 100644 --- a/packages/@biomejs/biome/configuration_schema.json +++ b/packages/@biomejs/biome/configuration_schema.json @@ -3944,7 +3944,7 @@ ] }, "useSortedObjectProperties": { - "description": "Enforce ordering of JS objects properties.", + "description": "Enforce ordering of a JS object properties.", "anyOf": [ { "$ref": "#/definitions/RuleAssistConfiguration_for_Null" }, { "type": "null" } From 15ef22f247ee15793dfb97d2f735e4cc30387b5e Mon Sep 17 00:00:00 2001 From: Sasha <64744993+r1tsuu@users.noreply.github.com> Date: Tue, 11 Feb 2025 22:49:23 +0200 Subject: [PATCH 5/6] refactor: rename rule to `useSortedKeys` --- .changeset/stupid-adults-crash.md | 2 +- .../src/analyzer/assist/actions.rs | 23 ++----------------- crates/biome_js_analyze/src/assist/source.rs | 4 ++-- ...bject_properties.rs => use_sorted_keys.rs} | 6 ++--- crates/biome_js_analyze/src/options.rs | 3 ++- .../sorted.js | 0 .../sorted.js.snap | 0 .../unsorted.js | 0 .../unsorted.js.snap | 0 .../@biomejs/backend-jsonrpc/src/workspace.ts | 4 ---- .../@biomejs/biome/configuration_schema.json | 7 ------ 11 files changed, 10 insertions(+), 39 deletions(-) rename crates/biome_js_analyze/src/assist/source/{use_sorted_object_properties.rs => use_sorted_keys.rs} (97%) rename crates/biome_js_analyze/tests/specs/source/{useSortedObjectProperties => useSortedKeys}/sorted.js (100%) rename crates/biome_js_analyze/tests/specs/source/{useSortedObjectProperties => useSortedKeys}/sorted.js.snap (100%) rename crates/biome_js_analyze/tests/specs/source/{useSortedObjectProperties => useSortedKeys}/unsorted.js (100%) rename crates/biome_js_analyze/tests/specs/source/{useSortedObjectProperties => useSortedKeys}/unsorted.js.snap (100%) diff --git a/.changeset/stupid-adults-crash.md b/.changeset/stupid-adults-crash.md index 068e6efdabc4..61ec0688825d 100644 --- a/.changeset/stupid-adults-crash.md +++ b/.changeset/stupid-adults-crash.md @@ -2,7 +2,7 @@ "@biomejs/biome": minor --- -Add a new assist rule - `useSortedObjectProperties` which enforces ordering of a JS object properties. +Add a new JS 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. diff --git a/crates/biome_configuration/src/analyzer/assist/actions.rs b/crates/biome_configuration/src/analyzer/assist/actions.rs index 2c3fd75bb82b..08da0f94a2b5 100644 --- a/crates/biome_configuration/src/analyzer/assist/actions.rs +++ b/crates/biome_configuration/src/analyzer/assist/actions.rs @@ -131,10 +131,6 @@ pub struct Source { #[serde(skip_serializing_if = "Option::is_none")] pub use_sorted_keys: Option>, - #[doc = "Enforce ordering of a JS object properties."] - #[serde(skip_serializing_if = "Option::is_none")] - pub use_sorted_object_properties: - Option>, #[doc = "Enforce ordering of CSS properties and nested rules."] #[serde(skip_serializing_if = "Option::is_none")] pub use_sorted_properties: @@ -146,7 +142,6 @@ impl Source { "organizeImports", "useSortedAttributes", "useSortedKeys", - "useSortedObjectProperties", "useSortedProperties", ]; const RECOMMENDED_RULES_AS_FILTERS: &'static [RuleFilter<'static>] = @@ -178,14 +173,9 @@ impl Source { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[2])); } } - if let Some(rule) = self.use_sorted_object_properties.as_ref() { - if rule.is_enabled() { - index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[3])); - } - } if let Some(rule) = self.use_sorted_properties.as_ref() { if rule.is_enabled() { - index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[4])); + index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[3])); } } index_set @@ -207,14 +197,9 @@ impl Source { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[2])); } } - if let Some(rule) = self.use_sorted_object_properties.as_ref() { - if rule.is_disabled() { - index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[3])); - } - } if let Some(rule) = self.use_sorted_properties.as_ref() { if rule.is_disabled() { - index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[4])); + index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[3])); } } index_set @@ -250,10 +235,6 @@ impl Source { .use_sorted_keys .as_ref() .map(|conf| (conf.level(), conf.get_options())), - "useSortedObjectProperties" => self - .use_sorted_object_properties - .as_ref() - .map(|conf| (conf.level(), conf.get_options())), "useSortedProperties" => self .use_sorted_properties .as_ref() diff --git a/crates/biome_js_analyze/src/assist/source.rs b/crates/biome_js_analyze/src/assist/source.rs index 2ae96be8e36a..cee3640f65cd 100644 --- a/crates/biome_js_analyze/src/assist/source.rs +++ b/crates/biome_js_analyze/src/assist/source.rs @@ -5,5 +5,5 @@ use biome_analyze::declare_assist_group; pub mod organize_imports; pub mod use_sorted_attributes; -pub mod use_sorted_object_properties; -declare_assist_group! { pub Source { name : "source" , rules : [self :: organize_imports :: OrganizeImports , self :: use_sorted_attributes :: UseSortedAttributes , self :: use_sorted_object_properties :: UseSortedObjectProperties ,] } } +pub mod use_sorted_keys; +declare_assist_group! { pub Source { name : "source" , rules : [self :: organize_imports :: OrganizeImports , self :: use_sorted_attributes :: UseSortedAttributes , self :: use_sorted_keys :: UseSortedKeys ,] } } diff --git a/crates/biome_js_analyze/src/assist/source/use_sorted_object_properties.rs b/crates/biome_js_analyze/src/assist/source/use_sorted_keys.rs similarity index 97% rename from crates/biome_js_analyze/src/assist/source/use_sorted_object_properties.rs rename to crates/biome_js_analyze/src/assist/source/use_sorted_keys.rs index 7627549f0d7f..43f5ffee7270 100644 --- a/crates/biome_js_analyze/src/assist/source/use_sorted_object_properties.rs +++ b/crates/biome_js_analyze/src/assist/source/use_sorted_keys.rs @@ -66,15 +66,15 @@ declare_source_rule! { /// q: 1, /// } /// ``` - pub UseSortedObjectProperties { + pub UseSortedKeys { version: "next", - name: "useSortedObjectProperties", + name: "useSortedKeys", language: "js", recommended: false, } } -impl Rule for UseSortedObjectProperties { +impl Rule for UseSortedKeys { type Query = Ast; type State = Vec>; type Signals = Option; diff --git a/crates/biome_js_analyze/src/options.rs b/crates/biome_js_analyze/src/options.rs index bcdb1cf0af12..c1da25a985f2 100644 --- a/crates/biome_js_analyze/src/options.rs +++ b/crates/biome_js_analyze/src/options.rs @@ -413,7 +413,8 @@ pub type UseSortedAttributes = ::Options; pub type UseSortedClasses = ::Options; -pub type UseSortedObjectProperties = < assist :: source :: use_sorted_object_properties :: UseSortedObjectProperties as biome_analyze :: Rule > :: Options ; +pub type UseSortedKeys = + ::Options; pub type UseStrictMode = ::Options; pub type UseTemplate = ::Options; diff --git a/crates/biome_js_analyze/tests/specs/source/useSortedObjectProperties/sorted.js b/crates/biome_js_analyze/tests/specs/source/useSortedKeys/sorted.js similarity index 100% rename from crates/biome_js_analyze/tests/specs/source/useSortedObjectProperties/sorted.js rename to crates/biome_js_analyze/tests/specs/source/useSortedKeys/sorted.js diff --git a/crates/biome_js_analyze/tests/specs/source/useSortedObjectProperties/sorted.js.snap b/crates/biome_js_analyze/tests/specs/source/useSortedKeys/sorted.js.snap similarity index 100% rename from crates/biome_js_analyze/tests/specs/source/useSortedObjectProperties/sorted.js.snap rename to crates/biome_js_analyze/tests/specs/source/useSortedKeys/sorted.js.snap diff --git a/crates/biome_js_analyze/tests/specs/source/useSortedObjectProperties/unsorted.js b/crates/biome_js_analyze/tests/specs/source/useSortedKeys/unsorted.js similarity index 100% rename from crates/biome_js_analyze/tests/specs/source/useSortedObjectProperties/unsorted.js rename to crates/biome_js_analyze/tests/specs/source/useSortedKeys/unsorted.js diff --git a/crates/biome_js_analyze/tests/specs/source/useSortedObjectProperties/unsorted.js.snap b/crates/biome_js_analyze/tests/specs/source/useSortedKeys/unsorted.js.snap similarity index 100% rename from crates/biome_js_analyze/tests/specs/source/useSortedObjectProperties/unsorted.js.snap rename to crates/biome_js_analyze/tests/specs/source/useSortedKeys/unsorted.js.snap diff --git a/packages/@biomejs/backend-jsonrpc/src/workspace.ts b/packages/@biomejs/backend-jsonrpc/src/workspace.ts index 1413e627e9cb..a3231211468d 100644 --- a/packages/@biomejs/backend-jsonrpc/src/workspace.ts +++ b/packages/@biomejs/backend-jsonrpc/src/workspace.ts @@ -839,10 +839,6 @@ export interface Source { * Sorts the keys of a JSON object in natural order */ useSortedKeys?: RuleAssistConfiguration_for_Null; - /** - * Enforce ordering of a JS object properties. - */ - useSortedObjectProperties?: RuleAssistConfiguration_for_Null; /** * Enforce ordering of CSS properties and nested rules. */ diff --git a/packages/@biomejs/biome/configuration_schema.json b/packages/@biomejs/biome/configuration_schema.json index ece8df637b2b..6f5c60349c68 100644 --- a/packages/@biomejs/biome/configuration_schema.json +++ b/packages/@biomejs/biome/configuration_schema.json @@ -3943,13 +3943,6 @@ { "type": "null" } ] }, - "useSortedObjectProperties": { - "description": "Enforce ordering of a JS object properties.", - "anyOf": [ - { "$ref": "#/definitions/RuleAssistConfiguration_for_Null" }, - { "type": "null" } - ] - }, "useSortedProperties": { "description": "Enforce ordering of CSS properties and nested rules.", "anyOf": [ From 79ee29418cc10be71eb62e5c3c4cf6d01b975160 Mon Sep 17 00:00:00 2001 From: Sasha <64744993+r1tsuu@users.noreply.github.com> Date: Wed, 12 Feb 2025 20:05:55 +0200 Subject: [PATCH 6/6] chore: rename changeset filename --- ...lts-crash.md => add_the_new_js_assist_rule_use_sorted_keys.md} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename .changeset/{stupid-adults-crash.md => add_the_new_js_assist_rule_use_sorted_keys.md} (100%) diff --git a/.changeset/stupid-adults-crash.md b/.changeset/add_the_new_js_assist_rule_use_sorted_keys.md similarity index 100% rename from .changeset/stupid-adults-crash.md rename to .changeset/add_the_new_js_assist_rule_use_sorted_keys.md