feat(lint): add useMemberOrdering nursery rule#9042
feat(lint): add useMemberOrdering nursery rule#9042thilllon wants to merge 1 commit intobiomejs:mainfrom
Conversation
🦋 Changeset detectedLatest commit: f5826d8 The changes in this PR will be included in the next version bump. This PR includes changesets to release 13 packages
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 |
a3f8fb1 to
7922bd8
Compare
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
WalkthroughAdds a new nursery lint rule Suggested reviewers
🚥 Pre-merge checks | ✅ 2✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
@coderabbitai review |
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Fix all issues with AI agents
In `@crates/biome_js_analyze/src/lint/nursery/use_member_ordering.rs`:
- Around line 90-96: The diagnostic currently emits a hardcoded note in the
.note(markup! { "Members should be ordered by: properties, constructors,
methods." }) call which is misleading for non-default or user-configured orders;
update the code in use_member_ordering.rs to either remove this static note or
build the note text dynamically from the active ordering settings (the rule's
configured order) and use that generated string in the .note(...) invocation
(refer to the place where .note(markup! { ... }) is called and the state/options
that contain the ordering to compose the message).
- Line 54: The rule registration currently uses
RuleSource::EslintTypeScript("member-ordering").same() which incorrectly claims
identical behavior; change it to
RuleSource::EslintTypeScript("member-ordering").inspired() to indicate we only
mirror some class-member ordering behavior (not full
interface/type/enum/memberTypes/optionalityOrder/order support). Update the
entry where sources: &[RuleSource::EslintTypeScript("member-ordering").same()]
is defined to use .inspired() so the rule source accurately reflects
partial/modified behavior.
- Around line 427-451: In find_order_violations, prev_rank currently stores the
last seen member's rank which lets lower-ranked violating members lower the
baseline and mask later violations; change the logic so prev_rank tracks the
maximum rank seen so far (and its label) instead of the immediate predecessor:
when you compute rank = group.rank(order), if rank < prev_r push the
MemberOrderViolation (using member_range and expected_before_name), but do NOT
set prev_rank to the lower rank—instead set prev_rank = Some((max(prev_r, rank),
label_for_max)) so prev_rank always holds the highest rank and its corresponding
label; update references to prev_label/prev_r accordingly in the loop.
🧹 Nitpick comments (2)
crates/biome_js_analyze/src/lint/nursery/use_member_ordering.rs (1)
102-229:Accessor/StaticAccessor/ etc. groups are indefault_order()but never classified.
classify_membermaps getters →GetAccessor*and setters →SetAccessor*, but never returns the combinedAccessor*variants. Those combined groups occupy rank positions in the default order, effectively acting as dead slots. This isn't a bug per se, but it means the combined accessor groups are only useful in custom configurations, which could confuse users expecting them to work out of the box.Consider either documenting this clearly or removing the combined accessor entries from
default_order().crates/biome_rule_options/src/use_member_ordering.rs (1)
134-192:default_order()allocates a newVecon every call — consider a static slice.
groups()callsdefault_order()which builds a fresh 44-elementVeceach time. Since the default never changes, a&'static [MemberGroup]constant would avoid the allocation entirely and letgroups()return aVeconly when the user provides a custom order.Not urgent — this is called once per class — but it's a tidy improvement.
Sketch
const DEFAULT_ORDER: &[MemberGroup] = &[ MemberGroup::IndexSignature, MemberGroup::StaticIndexSignature, // ... all variants ... MemberGroup::StaticBlock, ]; impl MemberGroup { pub fn default_order() -> &'static [MemberGroup] { DEFAULT_ORDER } }Then adjust
groups()andrank()signatures to accept&[MemberGroup](which they already do on the consumer side).
crates/biome_js_analyze/src/lint/nursery/use_member_ordering.rs
Outdated
Show resolved
Hide resolved
crates/biome_js_analyze/src/lint/nursery/use_member_ordering.rs
Outdated
Show resolved
Hide resolved
crates/biome_js_analyze/src/lint/nursery/use_member_ordering.rs
Outdated
Show resolved
Hide resolved
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Fix all issues with AI agents
In `@crates/biome_js_analyze/src/lint/nursery/use_member_ordering.rs`:
- Around line 88-100: The current deduplication uses
label.split_whitespace().last() which truncates meaningful group names (symbols:
seen, order, label, broad, order_description) — change this to use the full
group label (or map each MemberGroup variant to an explicit, human-friendly
broad category) and dedupe while preserving order: iterate over order, derive
the full label or mapped category from the MemberGroup variant instead of using
split_whitespace().last(), track seen categories with a HashSet (or Vec +
contains) to avoid duplicates, push the full category strings into seen, and
then join seen into order_description so the resulting message uses clear,
complete group names.
- Around line 455-467: The current logic uses group.rank(order) and treats the
sentinel value order.len() like a normal rank, which causes unlisted groups to
inflate max_rank and wrongly trigger MemberOrderViolation; change the comparison
in the member-order loop so that when group.rank(order) == order.len() you skip
that member (do not compare against or assign to max_rank and do not push a
violation for it), leaving max_rank unchanged for subsequent listed groups;
reference the symbols max_rank, group.rank(order), MemberOrderViolation,
member_range and expected_before_name when locating and updating the code.
🧹 Nitpick comments (2)
crates/biome_js_analyze/src/lint/nursery/use_member_ordering.rs (2)
117-244: Consider extracting shared classification logic to reduce repetition.The property, method, getter, and setter branches all follow the same pattern: extract
is_static,is_hash_private,accessibility, then callresolve_*_group. A small generic helper could collapse these ~120 lines significantly. Not urgent, but would help maintainability as the rule evolves.
263-370: Could reduce boilerplate with a declarative macro.The five
has_static_modifier_*and fourget_*_accessibilityfunctions are structurally identical — only the types and variants differ. A smallmacro_rules!could generate them all. Purely optional, but would cut ~100 lines.
crates/biome_js_analyze/src/lint/nursery/use_member_ordering.rs
Outdated
Show resolved
Hide resolved
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Fix all issues with AI agents
In `@crates/biome_js_analyze/src/lint/nursery/use_member_ordering.rs`:
- Around line 210-219: The TS getter/setter signature branches hardcode
is_hash_private=false; instead determine hash-private from the member name like
other cases: call is_hash_private_name on the signature's name (e.g. use
getter.name() / setter.name() to get the AnyJsClassMemberName and pass it to
is_hash_private_name) and pass that boolean into resolve_get_accessor_group /
resolve_set_accessor_group; keep existing is_static
(has_static_modifier_ts_method) and accessibility logic intact.
🧹 Nitpick comments (1)
crates/biome_js_analyze/src/lint/nursery/use_member_ordering.rs (1)
258-365: Consider a macro to reduce the modifier-helper boilerplate.Five
has_static_modifier_*and fourget_*_accessibilityfunctions are structurally identical, differing only in the modifier list type and variant path. A declarative macro could generate all of them from a table of(fn_name, list_type, variant_prefix)tuples, cutting ~110 lines down to ~20.Not blocking — the current code is correct and the types unfortunately don't share a trait.
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
Merging this PR will degrade performance by 6.55%
Performance Changes
Comparing Footnotes
|
| impl Rule for UseMemberOrdering { | ||
| type Query = Ast<JsClassMemberList>; | ||
| type State = MemberOrderViolation; | ||
| type Signals = Vec<Self::State>; |
There was a problem hiding this comment.
nit: boxed slice instead of Vec
| type Signals = Vec<Self::State>; | |
| type Signals = Box<[Self::State]>; |
| } | ||
| ``` | ||
|
|
||
| The default order is: index signatures, properties, accessors, constructors, methods, static blocks. The order is fully configurable via a `groups` option. |
There was a problem hiding this comment.
This option is undocumented in the rule.
| customOrder.options:2:5 deserialize ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ | ||
|
|
||
| × Found an unknown key `options`. | ||
|
|
||
| 1 │ { | ||
| > 2 │ "options": { | ||
| │ ^^^^^^^^^ | ||
| 3 │ "groups": ["constructor", "method", "property"] | ||
| 4 │ } | ||
|
|
||
| i Known keys: |
There was a problem hiding this comment.
this diagnostic shouldn't be here
| class InvalidCustom { | ||
| name; | ||
| constructor() {} | ||
| } |
There was a problem hiding this comment.
split this into 2, one valid and the other invalid. include the magic comments at the top to flag which one should or shouldn't emit diagnostics:
/* should not generate diagnostics *//* should generate diagnostics */
| if rank < max_r { | ||
| violations.push(MemberOrderViolation { | ||
| member_range: *range, | ||
| expected_before_name: max_label.to_string(), |
There was a problem hiding this comment.
avoid string allocation, use TokenText instead
| }; | ||
| let rank = group.rank(order); | ||
| // Skip members whose group is not listed in the configured order | ||
| if rank == sentinel { |
There was a problem hiding this comment.
this check doesn't look right to me. wouldn't it truncate instead of filter groups out? I could be misreading.
| .note(markup! { | ||
| "Members should be ordered by: "{order_description}"." |
There was a problem hiding this comment.
IIRC there's a footer_list helper that lets you avoid the string allocation here.
e88e4f5 to
8d96045
Compare
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Fix all issues with AI agents
In `@crates/biome_js_analyze/src/lint/nursery/use_member_ordering.rs`:
- Around line 152-210: classify_member() currently only returns GetAccessor and
SetAccessor but the MemberGroup enum and default_order() include combined
variants like Accessor/StaticAccessor/ProtectedAccessor that will never be
produced; either remove those combined Accessor variants and their ranks from
MemberGroup and default_order() or, if they are reserved for TC39 auto-accessor
support, add a clear comment on the enum and in default_order() explaining they
are placeholders for the proposal and why classify_member() doesn't produce
them; update any code that matches on these combined variants (e.g.,
default_order(), ranking logic) to reflect the removal or to document planned
future support so custom orders like ["property","accessor","method"] behave as
expected.
- Around line 58-88: The rustdoc lists member group names in camelCase (e.g.,
indexSignature, hashPrivateProperty, staticBlock) but the actual deserialised
names are defined by the MemberGroup enum via #[serde(rename = "...")] and the
Deserializable macro (which expects kebab-case and `#private-`… forms); update the
documentation comment above use_member_ordering.rs to list the exact JSON keys
that the enum accepts (the serde-renamed variants such as index-signature,
static-index-signature, property, static-property, `#private-property` or
`#private-`… notation used in the enum, constructor, static-block, etc.) so copied
examples match the MemberGroup enum/Deserializable expectations (refer to
MemberGroup enum and the Deserializable macro for the canonical names to
document).
🧹 Nitpick comments (2)
crates/biome_rule_options/src/use_member_ordering.rs (1)
136-192: Consider makingdefault_ordera const orLazyLock<Vec<…>>.
default_order()allocates a freshVecof ~43 elements on every call. It's invoked in bothrun()anddiagnostic()(the latter once per violation). For a class with many members, this could mean several allocations of the same data.A
constarray or astatic LazyLockwould avoid the repeated heap allocation.♻️ Sketch using a const array
- pub fn default_order() -> Vec<MemberGroup> { - vec![ + pub const DEFAULT_ORDER: &'static [MemberGroup] = &[ // Index signatures MemberGroup::IndexSignature, MemberGroup::StaticIndexSignature, // ...same entries... MemberGroup::StaticBlock, - ] - } + ]; + + pub fn default_order() -> Vec<MemberGroup> { + Self::DEFAULT_ORDER.to_vec() + }Then the callers that only need
&[MemberGroup]can reference the const directly.crates/biome_js_analyze/src/lint/nursery/use_member_ordering.rs (1)
126-149: Diagnostic recomputesgroups()and deduplication for every violation.
options.groups()clones the fullVec<MemberGroup>and the broad-category dedup loop runs on eachdiagnostic()invocation. For a class with many out-of-order members, this is repeated work. Consider caching the order description string inMemberOrderViolationor computing it once via a shared approach.
| /// Classify a class member into its `MemberGroup`. | ||
| fn classify_member(member: &AnyJsClassMember) -> Option<MemberGroup> { | ||
| match member { | ||
| AnyJsClassMember::JsConstructorClassMember(_) => Some(MemberGroup::Constructor), | ||
| AnyJsClassMember::JsPropertyClassMember(prop) => { | ||
| let is_static = has_static_modifier_property(&prop.modifiers()); | ||
| let is_hash_private = prop | ||
| .name() | ||
| .ok() | ||
| .is_some_and(|n| is_hash_private_name(&n)); | ||
| let accessibility = get_property_accessibility(&prop.modifiers()); | ||
| Some(resolve_property_group( | ||
| is_static, | ||
| &accessibility, | ||
| is_hash_private, | ||
| )) | ||
| } | ||
| AnyJsClassMember::JsMethodClassMember(method) => { | ||
| let is_static = has_static_modifier_method(&method.modifiers()); | ||
| let is_hash_private = method | ||
| .name() | ||
| .ok() | ||
| .is_some_and(|n| is_hash_private_name(&n)); | ||
| let accessibility = get_method_accessibility(&method.modifiers()); | ||
| Some(resolve_method_group( | ||
| is_static, | ||
| &accessibility, | ||
| is_hash_private, | ||
| )) | ||
| } | ||
| AnyJsClassMember::JsGetterClassMember(getter) => { | ||
| let is_static = has_static_modifier_method(&getter.modifiers()); | ||
| let is_hash_private = getter | ||
| .name() | ||
| .ok() | ||
| .is_some_and(|n| is_hash_private_name(&n)); | ||
| let accessibility = get_method_accessibility(&getter.modifiers()); | ||
| Some(resolve_get_accessor_group( | ||
| is_static, | ||
| &accessibility, | ||
| is_hash_private, | ||
| )) | ||
| } | ||
| AnyJsClassMember::JsSetterClassMember(setter) => { | ||
| let is_static = has_static_modifier_method(&setter.modifiers()); | ||
| let is_hash_private = setter | ||
| .name() | ||
| .ok() | ||
| .is_some_and(|n| is_hash_private_name(&n)); | ||
| let accessibility = get_method_accessibility(&setter.modifiers()); | ||
| Some(resolve_set_accessor_group( | ||
| is_static, | ||
| &accessibility, | ||
| is_hash_private, | ||
| )) | ||
| } | ||
| AnyJsClassMember::JsStaticInitializationBlockClassMember(_) => { | ||
| Some(MemberGroup::StaticBlock) | ||
| } |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
# First, let's find the MemberGroup enum definition
rg -A 30 "enum MemberGroup" crates/biome_js_analyze/src/lint/nursery/use_member_ordering.rs | head -50Repository: biomejs/biome
Length of output: 39
🏁 Script executed:
# Check the AnyJsClassMember definition in biome_js_syntax
fd "nodes.rs" crates/biome_js_syntax/src/generated/ | head -1 | xargs rg -A 50 "enum AnyJsClassMember" | head -70Repository: biomejs/biome
Length of output: 2748
🏁 Script executed:
# Look for the default_order function to see what MemberGroup variants are listed
rg -B 5 -A 50 "fn default_order" crates/biome_js_analyze/src/lint/nursery/use_member_ordering.rsRepository: biomejs/biome
Length of output: 39
🏁 Script executed:
# Find MemberGroup enum definition more directly
rg "enum MemberGroup" crates/biome_js_analyze/src/lint/nursery/use_member_ordering.rs -A 50Repository: biomejs/biome
Length of output: 39
🏁 Script executed:
# Find the default_order function
rg "default_order\|fn.*default" crates/biome_js_analyze/src/lint/nursery/use_member_ordering.rs -B 2 -A 30Repository: biomejs/biome
Length of output: 39
🏁 Script executed:
# Check if there are any mentions of "Accessor" in MemberGroup or default_order context
rg "Accessor" crates/biome_js_analyze/src/lint/nursery/use_member_ordering.rs | head -20Repository: biomejs/biome
Length of output: 1765
🏁 Script executed:
# Read the file to find MemberGroup enum definition
cat -n crates/biome_js_analyze/src/lint/nursery/use_member_ordering.rs | grep -A 100 "^[[:space:]]*[0-9]*[[:space:]]*enum MemberGroup" | head -120Repository: biomejs/biome
Length of output: 39
🏁 Script executed:
# Also check the file structure - get line count and see the enum at beginning
wc -l crates/biome_js_analyze/src/lint/nursery/use_member_ordering.rsRepository: biomejs/biome
Length of output: 124
🏁 Script executed:
# Read from the start of the file to find MemberGroup
head -200 crates/biome_js_analyze/src/lint/nursery/use_member_ordering.rs | tail -150Repository: biomejs/biome
Length of output: 5869
🏁 Script executed:
# Read the beginning of the file to find MemberGroup enum
head -100 crates/biome_js_analyze/src/lint/nursery/use_member_ordering.rsRepository: biomejs/biome
Length of output: 3569
🏁 Script executed:
# Find the MemberGroup enum definition in biome_rule_options
find . -name "*.rs" -path "*/biome_rule_options/*" | xargs grep -l "enum MemberGroup" | head -5Repository: biomejs/biome
Length of output: 111
🏁 Script executed:
# Broader search for MemberGroup enum definition
fd "use_member_ordering" --type f | xargs grep -l "enum MemberGroup"Repository: biomejs/biome
Length of output: 109
🏁 Script executed:
# Read the MemberGroup enum definition file
cat -n crates/biome_rule_options/src/use_member_ordering.rsRepository: biomejs/biome
Length of output: 14949
Combined Accessor groups are dead entries — they'll never match getters or setters.
classify_member() produces only GetAccessor and SetAccessor variants. The combined Accessor, StaticAccessor, ProtectedAccessor, etc. live in the enum and default_order() but no code path ever creates them. This means:
- In the default order: inert rank slots (noise, no functional bug).
- In a custom order like
["property", "accessor", "method"]: users would expect getters and setters to match"accessor", but they won't—they'll silently fall through to the sentinel rank.
If these are placeholders for the TC39 auto-accessor proposal (accessor name;), add a comment explaining that. If not, remove them and their ranks from default_order().
🤖 Prompt for AI Agents
In `@crates/biome_js_analyze/src/lint/nursery/use_member_ordering.rs` around lines
152 - 210, classify_member() currently only returns GetAccessor and SetAccessor
but the MemberGroup enum and default_order() include combined variants like
Accessor/StaticAccessor/ProtectedAccessor that will never be produced; either
remove those combined Accessor variants and their ranks from MemberGroup and
default_order() or, if they are reserved for TC39 auto-accessor support, add a
clear comment on the enum and in default_order() explaining they are
placeholders for the proposal and why classify_member() doesn't produce them;
update any code that matches on these combined variants (e.g., default_order(),
ranking logic) to reflect the removal or to document planned future support so
custom orders like ["property","accessor","method"] behave as expected.
There was a problem hiding this comment.
this might also be applicable
32bd5ac to
6b59239
Compare
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
6b59239 to
393c198
Compare
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
There was a problem hiding this comment.
🧹 Nitpick comments (2)
crates/biome_js_analyze/src/lint/nursery/use_member_ordering.rs (2)
310-403: Consider reducing modifier-helper duplication with a macro or trait.There are 8 near-identical functions for extracting static/accessibility info from different modifier list types. A small declarative macro could collapse them:
💡 Sketch
macro_rules! impl_modifier_helpers { ($static_fn:ident, $acc_fn:ident, $list_ty:ty, $mod_enum:path, $static_variant:pat, $acc_variant:pat) => { fn $static_fn(modifiers: &$list_ty) -> bool { modifiers.into_iter().any(|m| matches!(m, $static_variant)) } fn $acc_fn(modifiers: &$list_ty) -> Accessibility { for m in modifiers { if let $acc_variant = m { return ts_accessibility_to_enum(&acc); } } Accessibility::Public } }; }Entirely optional — the current code is clear and the repetition mirrors biome's typed-AST style.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@crates/biome_js_analyze/src/lint/nursery/use_member_ordering.rs` around lines 310 - 403, The eight near-identical helper functions (has_static_modifier_property, get_property_accessibility, has_static_modifier_method, get_method_accessibility, has_static_modifier_index, has_static_modifier_ts_property, get_ts_property_accessibility, has_static_modifier_ts_method, get_ts_method_accessibility) can be collapsed with a small declarative macro to remove duplication; add a macro (e.g., impl_modifier_helpers) that takes the static fn name, accessibility fn name, the modifier list type, the modifier enum path, the static variant pattern and the accessibility variant pattern and expands to the two functions (static check using .into_iter().any(|m| matches!(m, $static_variant)) and accessibility getter iterating and returning ts_accessibility_to_enum when matching $acc_variant, defaulting to Accessibility::Public) and replace the explicit implementations with macro invocations for each modifier-list type.
128-151: Diagnostic rebuilds the category list on every invocation.
diagnostic()recomputesoptions.groups()and theseenbroad-category list for each violation. For the typical number of violations per class this is negligible, but if you ever want to tighten it up, the list could be computed once inrun()and stored alongside eachMemberOrderViolation.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@crates/biome_js_analyze/src/lint/nursery/use_member_ordering.rs` around lines 128 - 151, The diagnostic() function recomputes options.groups() and the seen broad-category list for every violation; instead, compute the ordered broad-category list once in run() and attach it to the rule state or each MemberOrderViolation so diagnostic() can reuse it. Update run() (where MemberOrderViolation instances are created) to build the unique seen Vec from ctx.options().groups() and store that Vec on the State or include it as a field on MemberOrderViolation; then change diagnostic() to read that precomputed list (instead of recomputing options.groups() and rebuilding seen) while still using state.member_range and state.expected_before_name for the diagnostic text.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@crates/biome_js_analyze/src/lint/nursery/use_member_ordering.rs`:
- Around line 310-403: The eight near-identical helper functions
(has_static_modifier_property, get_property_accessibility,
has_static_modifier_method, get_method_accessibility, has_static_modifier_index,
has_static_modifier_ts_property, get_ts_property_accessibility,
has_static_modifier_ts_method, get_ts_method_accessibility) can be collapsed
with a small declarative macro to remove duplication; add a macro (e.g.,
impl_modifier_helpers) that takes the static fn name, accessibility fn name, the
modifier list type, the modifier enum path, the static variant pattern and the
accessibility variant pattern and expands to the two functions (static check
using .into_iter().any(|m| matches!(m, $static_variant)) and accessibility
getter iterating and returning ts_accessibility_to_enum when matching
$acc_variant, defaulting to Accessibility::Public) and replace the explicit
implementations with macro invocations for each modifier-list type.
- Around line 128-151: The diagnostic() function recomputes options.groups() and
the seen broad-category list for every violation; instead, compute the ordered
broad-category list once in run() and attach it to the rule state or each
MemberOrderViolation so diagnostic() can reuse it. Update run() (where
MemberOrderViolation instances are created) to build the unique seen Vec from
ctx.options().groups() and store that Vec on the State or include it as a field
on MemberOrderViolation; then change diagnostic() to read that precomputed list
(instead of recomputing options.groups() and rebuilding seen) while still using
state.member_range and state.expected_before_name for the diagnostic text.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
393c198 to
f5826d8
Compare
There was a problem hiding this comment.
I haven't looked at all the code, but there are clear errors that needs to be addressed.
- this can't be a lint rule but needs to be a code action
- we don't do nursery code actions, so it must a minor. PR must go to
nextbranch - adhere to PR template
- all options must be camel case
- options must have doc string comments
- there aren't enough tests: there tons of groups, and only 3 were tested.
- the name of the rule comply to our naming convention. See other actions to understand
|
|
||
| impl MemberGroup { | ||
| /// Returns the default order of member groups. | ||
| pub fn default_order() -> Vec<MemberGroup> { |
There was a problem hiding this comment.
Implement order using PartialOrd
Summary
useMemberOrderingthat enforces a consistent ordering of class members, corresponding to ESLint TypeScript's@typescript-eslint/member-ordering.groupsoption with 40+ member categories (properties, methods, accessors, constructors, static blocks, with static/accessibility/hash-private variations).Details
New files
crates/biome_rule_options/src/use_member_ordering.rs—MemberGroupenum andUseMemberOrderingOptionsstructcrates/biome_js_analyze/src/lint/nursery/use_member_ordering.rs— Rule implementation withclassify_member()for allAnyJsClassMembervariantsModified files
crates/biome_diagnostics_categories/src/categories.rs— Added category entrycrates/biome_rule_options/src/lib.rs— Registered modulecrates/biome_cli/src/execute/migrate/eslint_any_rule_to_biome.rs— Added@typescript-eslint/member-orderingmigration mappingTests
valid.js/valid.ts— Correct ordering cases (no diagnostics)invalid.js/invalid.ts— Incorrect ordering cases (diagnostics expected)customOrder.js+customOrder.options.json— Custom group order via optionsTest plan
cargo t use_member_ordering— 6 tests passcargo fmt— No formatting issuescargo insta acceptAI assistance disclosure
Made with Cursor