Skip to content

Conversation

@azat-io
Copy link
Owner

@azat-io azat-io commented Aug 10, 2025

Close #566.

@coderabbitai
Copy link

coderabbitai bot commented Aug 10, 2025

Note

Reviews paused

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.
📝 Walkthrough

Summary by CodeRabbit

Release Notes

  • New Features

    • Added two new ESLint rules: sort-import-attributes and sort-export-attributes for sorting import and export statement attributes.
    • Enhanced grouping capabilities across sorting rules with per-group option overrides (type, order, newlines).
    • Added search functionality to documentation site.
  • Improvements

    • Modernized configuration API with array-based customGroups definitions.
    • Expanded newline control options (newlinesBetween, partitionByNewLine) across sorting rules.
  • Breaking Changes

    • Migrated to ES modules; Node.js requirement updated to ^20.0.0 || >=22.0.0.

✏️ Tip: You can customize this high-level summary in your review settings.

Walkthrough

Project-wide migration to ESM and Node ≥20; replaced object-mapped customGroups with an array DSL; removed deprecated options (e.g., groupKind, ignorePattern); added per-group overrides and partition/newline controls; introduced two new rules (sort-import-attributes, sort-export-attributes); broad, coordinated updates to types, utils, rules, tests and docs; docs site search and UI features added.

Changes

Cohort / File(s) Summary
Package & Build
package.json, vite.config.ts
Switch package to ESM ("type":"module"); bump Node engines to `^20.0.0
Plugin entry & configs
index.ts, readme.md, docs/public/llms.txt
Added new rules sort-import-attributes and sort-export-attributes; introduced exported rules and configs maps; README/docs index updated.
New rules, types & tests
rules/sort-import-attributes.*, rules/sort-export-attributes.*, rules/*/types.ts, test/rules/*
Added two new ESLint rules with types, JSON schema, fixers and comprehensive tests.
customGroups migration
utils/*, rules/*, types/common-options.ts, utils/common-json-schemas.ts
Removed deprecated object-based customGroups; adopted array-based CustomGroupsOption across utils, validators and computeGroup; removed deprecatedCustomGroupsJsonSchema and related types.
Partitioning & newline controls
rules/*, rules/*/types.ts, utils/get-newlines-between-*.ts, docs/content/rules/*.mdx
Added partitionByComment, partitionByNewLine, numeric newlinesBetween, and per-group newlinesInside; wired JSON schemas, validation, runtime handling and docs.
Remove deprecated options
multiple rules/*, docs
Removed groupKind, ignorePattern, tsconfigRootDir, forceNumericSort, destructuring toggles; migrated rules to groups-centric configuration.
Utilities & filters
utils/filter-options-by-*.ts, utils/*
Renamed/added utilities (e.g., filterOptionsByAllNamesMatch, filterOptionsByDeclarationCommentMatches), tightened types to array-based customGroups, removed legacy matching branches.
Rule refactors & typing standardization
many rules/*.ts
Standardized option typing from Options[0]Options[number]; defaulted customGroups: []; removed per-node groupKind; centralized sortNodesByGroups and per-group override wiring; added meta.defaultOptions.
sort-enums changes
rules/sort-enums.*, rules/sort-enums/types.ts, test/*, docs/*
Replaced boolean sortByValue with `'always'
Tests
test/rules/*, test/utils/*
Extensive test updates: migrated to array-based customGroups, numeric newline semantics, renamed groups/message IDs, removed deprecated tests, added per-group/partition tests.
Docs & migration guidance
docs/content/rules/*.mdx
Rewrote documentation to describe array-based customGroups, per-group overrides, partition/newline options; removed deprecated sections and added migration notes and new rule pages.
Docs site UX & search
docs/components/*, docs/pages/*, docs/utils/*, docs/stores/*
Added search UI (SearchButton, SearchModal, HighlightText, Portal), client TOC script, SSR-aware stores, search-index route, and lifecycle/cleanup improvements (AbortController, swap handling).
Types composition changes
many rules/*/types.ts
Replaced many per-rule Options with array-based Partial<CommonGroupsOptions & CommonPartitionOptions & CommonOptions>[], added singleCustomGroupJsonSchema exports, removed deprecated common types.
Misc & CI
.github/*, astro.config.ts, docs CSS
Updated GitHub Actions pins, adjusted Astro config (prefetch defaultStrategy), minor style/site behavior tweaks.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant ESLint
  participant Rule
  participant Matcher as CustomGroupMatcher
  participant Partitioner
  participant Sorter
  participant Reporter

  ESLint->>Rule: visit AST node and collect attributes/members
  Rule->>Matcher: match item against array-based customGroups
  Matcher-->>Rule: returns groupName or 'unknown'
  Rule->>Partitioner: decide partitions (partitionByNewLine / partitionByComment)
  Partitioner-->>Rule: partitions[]
  loop per partition
    Rule->>Sorter: sort partition with per-group overrides (type/order/newlinesInside)
    Sorter-->>Rule: sorted nodes and spacing info
    Rule->>Reporter: emit diagnostics (group-order, element-order, spacing) with leftGroup/rightGroup context
  end
Loading

Estimated code review effort

🎯 5 (Critical) | ⏱️ ~120+ minutes

Areas needing extra attention:

  • New rules (sort-import-attributes, sort-export-attributes): schema, message IDs, fixer correctness, and tests.
  • computeGroup / custom-group matching semantics (first-match, anyOf, fallbackSort) and their type/schema alignment.
  • Partitioning/newlines interactions between partitionByComment, partitionByNewLine, newlinesBetween and per-group newlinesInside, including auto-fix behavior.
  • Large-scale test updates: ensure message IDs, diagnostic data fields (e.g., leftGroup/rightGroup), and fix outputs are consistent.
  • ESM build and DTS generation changes in vite.config.ts and package metadata (Node engines bump) — CI validation and package publishing flow.

Possibly related PRs

Suggested reviewers

  • hugop95

Pre-merge checks

❌ Failed checks (2 warnings, 1 inconclusive)
Check name Status Explanation Resolution
Description check ⚠️ Warning PR description only contains 'Close #566.' without substantive details about what this massive changeset accomplishes or why these changes matter. Expand the description to summarize key changes like ESM migration, deprecated API removals, new rules, and Node/ESLint version changes for clarity.
Docstring Coverage ⚠️ Warning Docstring coverage is 15.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
Out of Scope Changes check ❓ Inconclusive Changes like component lifecycle refactoring (AbortController patterns), search/modal UI additions, and Astro config updates appear beyond the core ESLint plugin scope outlined in #566. Clarify whether search UI, Astro documentation improvements, and component lifecycle changes are intentional v5.0.0 features or should be separated.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed PR title 'release v5.0.0' clearly and concisely summarizes the main change: preparing a major version release.
Linked Issues check ✅ Passed Changeset implements all major objectives from #566: ESM conversion, deprecated API removal, new rules (sort-import-attributes, sort-export-attributes), Node.js v18+ requirement, test refactoring with Vitest, and significant code reorganization.

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
vite.config.ts (1)

17-23: rollupOptions + preserveModules interplay — validate export paths

Using preserveModules with multiple lib entry points and a custom fileName can affect final paths. Cross-check that the files referenced in package.json exports (especially ./alphabet) match the generated structure.

If you want fully predictable entry locations, consider setting rollupOptions.output.entryFileNames explicitly (e.g., '[name].js') and aligning exports accordingly.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 649049b and e6b8187.

📒 Files selected for processing (2)
  • package.json (2 hunks)
  • vite.config.ts (1 hunks)
🧰 Additional context used
🪛 ESLint
vite.config.ts

[error] 27-27: Unsafe call of a(n) error type typed value.

(typescript/no-unsafe-call)

🔇 Additional comments (7)
package.json (4)

14-14: ESM-only transition acknowledged

Switching "type" to "module" aligns with the ESM-only objective. Ensure all Node-facing configs and scripts (and any code using __dirname/require) are ESM-safe.


129-129: Engines updated to Node 20+/22+ — good

This cleanly drops Node 18 in line with the plan to use newer language APIs (e.g., toSorted).


20-23: Verify the ./alphabet export path consistency (JS vs types)

Current mapping mixes paths:

  • types: "./dist/alphabet.d.ts"
  • default: "./dist/utils/alphabet.js"

Given preserveModules + custom fileName in Vite, confirm that both files exist at publish time. If the build flattens the entry to dist/alphabet.js (common with lib.fileName), align exports for consistency.

Two options (pick the one matching the actual build output):

  • If output is flattened:
   "./alphabet": {
-    "types": "./dist/alphabet.d.ts",
-    "default": "./dist/utils/alphabet.js"
+    "types": "./dist/alphabet.d.ts",
+    "default": "./dist/alphabet.js"
   },
  • If output preserves utils/:
   "./alphabet": {
-    "types": "./dist/alphabet.d.ts",
+    "types": "./dist/utils/alphabet.d.ts",
     "default": "./dist/utils/alphabet.js"
   },

Also ensure the dts plugin actually emits the corresponding .d.ts at the chosen location.


125-127: Align ESLint peerDependency with v9+ policy

The peerDependencies entry still permits ESLint v8 despite the stated objective to drop v8 support. Please confirm the intended minimum version and update accordingly:

• File: package.json (lines 125–127)
• Current snippet:

"peerDependencies": {
  "eslint": ">=8.45.0"
}

• Suggested change:

- "peerDependencies": {
-   "eslint": ">=8.45.0"
- },
+ "peerDependencies": {
+   "eslint": ">=9.0.0"
+ },

If v8 compatibility is intentionally retained, ensure the PR description, documentation, and changelog accurately reflect that decision.

vite.config.ts (3)

15-16: ESM-only build format — good

formats: ['es'] is consistent with the ESM-only package.json. This removes CJS output and matches ESLint v9’s ESM direction.


35-35: copyDtsFiles: true — streamlined d.ts generation

Looks good and complements the ESM setup. Just ensure it produces the files expected by package.json exports (e.g., ./alphabet).


27-27: Ensure Proper Typings for dts Plugin

ESLint flags dts(...) as an any call because TypeScript cannot resolve the default import’s types. Please verify that your root tsconfig.json (which extends @azat-io/typescript-config) enables:

esModuleInterop: true or allowSyntheticDefaultImports: true
• A moduleResolution mode supporting ES modules (e.g. "NodeNext" or "Bundler")

If those aren’t set, add them under compilerOptions in your root tsconfig.json.
Alternatively, you can:

  • Create a typed alias in vite.config.ts before calling dts:

    import type { Plugin } from 'vite'
    import dts, { type Options as DtsOptions } from 'vite-plugin-dts'
    
    const dtsPlugin: (options?: DtsOptions) => Plugin = dts
    
    // …
    plugins: [
      dtsPlugin({ /* … */ })
    ]
  • Or, as a last resort, disable the rule for that line:

    // eslint-disable-next-line @typescript-eslint/no-unsafe-call
    dts({ /* … */ })

Locations to verify:

  • vite.config.ts:27

@codecov
Copy link

codecov bot commented Aug 15, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 100.00%. Comparing base (100833f) to head (0403705).

Additional details and impacted files
@@            Coverage Diff             @@
##              main      #569    +/-   ##
==========================================
  Coverage   100.00%   100.00%            
==========================================
  Files          101       111    +10     
  Lines         8565      9011   +446     
  Branches      1688      1747    +59     
==========================================
+ Hits          8565      9011   +446     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

♻️ Duplicate comments (1)
vite.config.ts (1)

29-32: Same Node 20 compatibility issue: replace import.meta.dirname in dts include

The include paths will fail on Node 20. Use the same __dirname shim as above.

-        path.join(import.meta.dirname, 'index.ts'),
-        path.join(import.meta.dirname, 'types'),
-        path.join(import.meta.dirname, 'rules'),
-        path.join(import.meta.dirname, 'utils'),
+        path.join(__dirname, 'index.ts'),
+        path.join(__dirname, 'types'),
+        path.join(__dirname, 'rules'),
+        path.join(__dirname, 'utils'),
🧹 Nitpick comments (2)
vite.config.ts (2)

14-14: name is unused for ES format — consider removing

The lib.name option is only used for IIFE/UMD builds. For ES builds it’s ignored; removing it avoids confusion.

-      name: 'eslint-plugin-perfectionist',

27-27: ESLint: no-unsafe-call on dts(...) — ensure types or locally suppress

Static analysis flags dts(...) as an unsafe call, likely because the import is typed as any in this environment. If your TS setup doesn’t pick up vite-plugin-dts types, either assert the type or suppress for config files.

Options:

  • Type assertion:
import type { PluginOption } from 'vite'
(dts({
  // ...
}) as unknown as PluginOption)
  • Or disable the rule for this line/file:
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
dts({ /* ... */ })

Please confirm whether your linter is actually failing CI on this, and I can tailor the fix.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 5036e7b and 9f68cdd.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (2)
  • package.json (5 hunks)
  • vite.config.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • package.json
🧰 Additional context used
🪛 ESLint
vite.config.ts

[error] 27-27: Unsafe call of a(n) error type typed value.

(typescript/no-unsafe-call)

🔇 Additional comments (2)
vite.config.ts (2)

15-15: ESM-only build looks good

formats: ['es'] aligns with the ESM-only migration and ESLint 9.


35-35: Good addition: copyDtsFiles

copyDtsFiles: true helps keep declaration files in sync alongside preserveModules.

Comment on lines +10 to +12
path.resolve(import.meta.dirname, 'index.ts'),
path.resolve(import.meta.dirname, 'utils', 'alphabet.ts'),
],
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Fix: import.meta.dirname breaks on Node 20 — use ESM-safe __dirname

import.meta.dirname isn’t available in Node 20; this will throw at build time and contradicts engines: "^20.0.0 || >=22.0.0". Either bump engines to >=22 only or switch to an ESM-safe __dirname shim.

Apply this diff within the current block:

-        path.resolve(import.meta.dirname, 'index.ts'),
-        path.resolve(import.meta.dirname, 'utils', 'alphabet.ts'),
+        path.resolve(__dirname, 'index.ts'),
+        path.resolve(__dirname, 'utils', 'alphabet.ts'),

And add this near the imports (outside this hunk):

import { fileURLToPath } from 'node:url'

const __dirname = path.dirname(fileURLToPath(import.meta.url))
🤖 Prompt for AI Agents
In vite.config.ts around lines 10 to 12, import.meta.dirname is used which
breaks on Node 20; replace uses of import.meta.dirname with an ESM-safe
__dirname shim: add an import for fileURLToPath from 'node:url' and define const
__dirname = path.dirname(fileURLToPath(import.meta.url)) near the top imports,
then update the path.resolve calls in this block to use __dirname instead of
import.meta.dirname (do not change engines).

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

♻️ Duplicate comments (1)
vite.config.ts (1)

10-12: import.meta.dirname will break on Node 20 — use an ESM-safe __dirname shim

Your engines field allows Node 20, but import.meta.dirname is only available in Node 22+. Replace it with an ESM-safe __dirname shim to keep Node 20 support intact. This was already raised earlier; reiterating with a concrete, minimal fix.

Apply this diff within the selected lines:

-        path.resolve(import.meta.dirname, 'index.ts'),
-        path.resolve(import.meta.dirname, 'utils', 'alphabet.ts'),
+        path.resolve(__dirname, 'index.ts'),
+        path.resolve(__dirname, 'utils', 'alphabet.ts'),
-        path.join(import.meta.dirname, 'index.ts'),
-        path.join(import.meta.dirname, 'types'),
-        path.join(import.meta.dirname, 'rules'),
-        path.join(import.meta.dirname, 'utils'),
+        path.join(__dirname, 'index.ts'),
+        path.join(__dirname, 'types'),
+        path.join(__dirname, 'rules'),
+        path.join(__dirname, 'utils'),

Add this near the imports (outside the selected ranges):

import { fileURLToPath } from 'node:url'

const __dirname = path.dirname(fileURLToPath(import.meta.url))

Also applies to: 29-32

🧹 Nitpick comments (3)
vite.config.ts (3)

27-27: Silence no-unsafe-call by typing the dts factory

ESLint flagged this call as unsafe (any/unknown). Wrap the default export in a typed factory to satisfy the rule without changing behavior.

Apply this diff to the call site:

-    dts({
+    createDtsPlugin({

Add the following (outside the selected range, near the imports):

import type { PluginOption } from 'vite'
import type { PluginOptions } from 'vite-plugin-dts'

const createDtsPlugin: (options?: PluginOptions) => PluginOption = dts

2-2: Use vitest/config defineConfig so the test block is typed and discoverable

Importing defineConfig from vitest/config ensures the test property is properly typed and recognized by Vitest tooling.

-import { defineConfig } from 'vite'
+import { defineConfig } from 'vitest/config'

19-21: Nit: exports: 'auto' is unnecessary for ES-only output

This Rollup option is relevant for CJS. Since you’re emitting only ES modules, you can safely drop it.

       output: {
         preserveModules: true,
-        exports: 'auto',
       },
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 9f68cdd and e0cab92.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (2)
  • package.json (5 hunks)
  • vite.config.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • package.json
🧰 Additional context used
🪛 ESLint
vite.config.ts

[error] 27-27: Unsafe call of a(n) error type typed value.

(typescript/no-unsafe-call)

🔇 Additional comments (1)
vite.config.ts (1)

13-16: ESM-only build and preserved modules — LGTM

The switch to formats: ['es'] with preserveModules aligns with the ESM-only objective. File naming is consistent and explicit.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (3)
test/rules/sort-decorators.test.ts (1)

1-6998: Migrate object-based customGroups to the new array API
In test/rules/sort-decorators.test.ts, replace every

customGroups: { /* groupName: elementNamePattern [, …] */ },

with

customGroups: [
  { groupName: 'error', elementNamePattern: 'Error$' },
],

and for multiple entries:

- customGroups: { A: 'A', B: 'B' },
+ customGroups: [
+   { groupName: 'A', elementNamePattern: 'A' },
+   { groupName: 'B', elementNamePattern: 'B' },
+],
docs/content/rules/sort-decorators.mdx (2)

272-276: Update groups type to reflect inline newlines objects.

Examples use { newlinesBetween: ... } between groups, but the declared type omits these objects.

-<sub>
-  type: `Array<string | string[]>`
-</sub>
+<sub>
+  type: `Array<string | string[] | { newlinesBetween: 'always' | 'never' | number | 'ignore' }>`
+</sub>

Also applies to: 293-311


519-521: Fix test source link path.

The file lives under test/rules/sort-decorators.test.ts in this PR.

-- [Test source](https://github.com/azat-io/eslint-plugin-perfectionist/blob/main/test/sort-decorators.test.ts)
+- [Test source](https://github.com/azat-io/eslint-plugin-perfectionist/blob/main/test/rules/sort-decorators.test.ts)
🧹 Nitpick comments (7)
rules/sort-decorators/types.ts (3)

40-40: Redundant union: 'unknown' | string.

This widens to plain string; prefer just string for clarity.

-type Group = 'unknown' | string
+type Group = string

42-44: Make schema constant and non-reassignable.

Minor: declare as const to avoid accidental reassignment.

-export let singleCustomGroupJsonSchema: Record<string, JSONSchema4> = {
+export const singleCustomGroupJsonSchema: Record<string, JSONSchema4> = {
   elementNamePattern: regexJsonSchema,
 }

34-36: Add concise JSDoc on exported public types.

Public-facing types (Options, SingleCustomGroup) lack JSDoc; add brief comments to improve DX and align with PR objective.

Also applies to: 17-33

test/rules/sort-decorators.test.ts (1)

665-753: ESLint: no-unsafe-call on tagged templates (dedent).

Static analysis flags dedent template calls as unsafe (typed any/unknown). Two low-touch fixes:

  • Install proper types: add @types/dedent dev dep (or switch to ts-dedent).
  • Or disable the rule for this test file.

Options:

  1. Prefer proper typing
// package.json (devDependencies)
"@types/dedent": "^1.0.3"
  1. File-level disable (top of this test file)
/* eslint-disable @typescript-eslint/no-unsafe-call */

Also applies to: 808-883, 885-995, 997-1044, 1046-1109, 1110-1177, 1179-1254, 1256-1307, 1309-1423, 1425-1465, 1467-1517, 1519-1725, 4861-5030

docs/content/rules/sort-decorators.mdx (1)

247-253: Clarify partitionByNewLine description.

Minor wording to reflect “sort within newline-delimited partitions”.

-When `true`, the rule will not sort the decorators if there is an empty line between them.
+When `true`, blank lines create partitions: decorators are sorted within each partition but not moved across blank lines.
rules/sort-decorators.ts (2)

145-160: Broaden parameter-decorator detection to avoid false negatives.

The current check requires the decorated node to be an Identifier under a FunctionExpression. This can miss valid TS cases (e.g., TSParameterProperty, default/rest patterns). Relaxing the node-type check improves coverage without impacting class/property/class-decorator handlers.

Apply this minimal diff:

-        if (
-          'decorators' in decorator.parent &&
-          decorator.parent.type === 'Identifier' &&
-          decorator.parent.parent.type === 'FunctionExpression'
-        ) {
+        if (
+          'decorators' in decorator.parent &&
+          decorator.parent.parent?.type === 'FunctionExpression'
+        ) {

Would you like me to add tests for constructor parameters with parameter properties and default/rest patterns?


237-253: Nit: avoid repeated .at(-1) calls and correct partition index to be zero-based.

  • Minor perf/readability: cache the current bucket.
  • Partition IDs are typically zero-based; using length produces 1-based IDs.

Apply this diff:

-      let lastSortingNode = accumulator.at(-1)?.at(-1)
+      let bucket = accumulator[accumulator.length - 1]
+      let lastSortingNode = bucket.at(-1)
       if (
         shouldPartition({
           lastSortingNode,
           sortingNode,
           sourceCode,
           options,
         })
       ) {
-        accumulator.push([])
+        bucket = []
+        accumulator.push(bucket)
       }
 
-      accumulator.at(-1)!.push({
+      bucket.push({
         ...sortingNode,
-        partitionId: accumulator.length,
+        partitionId: accumulator.length - 1,
       })

If other utilities rely on 1-based IDs, keep the old value and skip the index tweak.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e0cab92 and 08f3844.

📒 Files selected for processing (4)
  • docs/content/rules/sort-decorators.mdx (5 hunks)
  • rules/sort-decorators.ts (5 hunks)
  • rules/sort-decorators/types.ts (1 hunks)
  • test/rules/sort-decorators.test.ts (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
rules/sort-decorators/types.ts (3)
types/common-options.ts (7)
  • CustomGroupsOption (103-140)
  • DeprecatedCustomGroupsOption (473-473)
  • PartitionByCommentOption (288-303)
  • NewlinesBetweenOption (203-226)
  • GroupsOptions (445-451)
  • CommonOptions (23-73)
  • RegexOption (499-499)
types/sorting-node.ts (1)
  • SortingNode (18-102)
utils/common-json-schemas.ts (1)
  • regexJsonSchema (237-246)
rules/sort-decorators.ts (6)
rules/sort-decorators/types.ts (1)
  • Options (17-32)
utils/common-json-schemas.ts (5)
  • deprecatedCustomGroupsJsonSchema (192-208)
  • buildCustomGroupsArrayJsonSchema (320-369)
  • partitionByNewLineJsonSchema (286-290)
  • newlinesBetweenJsonSchema (146-158)
  • groupsJsonSchema (165-190)
utils/report-errors.ts (4)
  • MISSED_SPACING_ERROR (33-34)
  • EXTRA_SPACING_ERROR (30-31)
  • GROUP_ORDER_ERROR (27-28)
  • ORDER_ERROR (21-22)
utils/validate-newlines-and-partition-configuration.ts (1)
  • validateNewlinesAndPartitionConfiguration (98-119)
utils/does-custom-group-match.ts (1)
  • doesCustomGroupMatch (121-141)
utils/get-custom-groups-compare-options.ts (1)
  • buildGetCustomGroupOverriddenOptionsFunction (143-154)
🪛 ESLint
test/rules/sort-decorators.test.ts

[error] 674-674: Unsafe use of a(n) error type typed template tag.

(typescript/no-unsafe-call)


[error] 701-701: Unsafe use of a(n) error type typed template tag.

(typescript/no-unsafe-call)


[error] 791-791: Unsafe use of a(n) error type typed template tag.

(typescript/no-unsafe-call)


[error] 798-798: Unsafe use of a(n) error type typed template tag.

(typescript/no-unsafe-call)


[error] 829-829: Unsafe use of a(n) error type typed template tag.

(typescript/no-unsafe-call)


[error] 851-851: Unsafe use of a(n) error type typed template tag.

(typescript/no-unsafe-call)


[error] 887-887: Unsafe use of a(n) error type typed template tag.

(typescript/no-unsafe-call)


[error] 929-929: Unsafe use of a(n) error type typed template tag.

(typescript/no-unsafe-call)


[error] 999-999: Unsafe use of a(n) error type typed template tag.

(typescript/no-unsafe-call)


[error] 1089-1089: Unsafe use of a(n) error type typed template tag.

(typescript/no-unsafe-call)


[error] 1099-1099: Unsafe use of a(n) error type typed template tag.

(typescript/no-unsafe-call)


[error] 1157-1157: Unsafe use of a(n) error type typed template tag.

(typescript/no-unsafe-call)


[error] 1166-1166: Unsafe use of a(n) error type typed template tag.

(typescript/no-unsafe-call)


[error] 1228-1228: Unsafe use of a(n) error type typed template tag.

(typescript/no-unsafe-call)


[error] 1240-1240: Unsafe use of a(n) error type typed template tag.

(typescript/no-unsafe-call)


[error] 1293-1293: Unsafe use of a(n) error type typed template tag.

(typescript/no-unsafe-call)


[error] 1300-1300: Unsafe use of a(n) error type typed template tag.

(typescript/no-unsafe-call)


[error] 1349-1349: Unsafe use of a(n) error type typed template tag.

(typescript/no-unsafe-call)


[error] 1354-1354: Unsafe use of a(n) error type typed template tag.

(typescript/no-unsafe-call)


[error] 1390-1390: Unsafe use of a(n) error type typed template tag.

(typescript/no-unsafe-call)


[error] 1416-1416: Unsafe use of a(n) error type typed template tag.

(typescript/no-unsafe-call)


[error] 1450-1450: Unsafe use of a(n) error type typed template tag.

(typescript/no-unsafe-call)


[error] 1457-1457: Unsafe use of a(n) error type typed template tag.

(typescript/no-unsafe-call)


[error] 1497-1497: Unsafe use of a(n) error type typed template tag.

(typescript/no-unsafe-call)


[error] 1506-1506: Unsafe use of a(n) error type typed template tag.

(typescript/no-unsafe-call)


[error] 1547-1547: Unsafe use of a(n) error type typed template tag.

(typescript/no-unsafe-call)


[error] 1553-1553: Unsafe use of a(n) error type typed template tag.

(typescript/no-unsafe-call)


[error] 1591-1591: Unsafe use of a(n) error type typed template tag.

(typescript/no-unsafe-call)


[error] 1596-1596: Unsafe use of a(n) error type typed template tag.

(typescript/no-unsafe-call)


[error] 1608-1608: Unsafe use of a(n) error type typed template tag.

(typescript/no-unsafe-call)


[error] 1655-1655: Unsafe use of a(n) error type typed template tag.

(typescript/no-unsafe-call)

🔇 Additional comments (10)
test/rules/sort-decorators.test.ts (5)

665-753: Great parametric coverage for elementNamePattern.

Covers strings, arrays, and regex objects; helps ensure RegexOption variants all work.


754-806: Solid tie-breaker test for fallbackSort.

Accurately validates line-length ties resolved via alphabetical fallback.

Also applies to: 808-883


885-995: Unsorted group behavior verified correctly.

Ensures intra-group order is preserved while enforcing group ordering.


1110-1177: Spacing matrix is comprehensive.

Nice coverage of global vs inline newlinesBetween and newlinesInside combinations.

Also applies to: 1179-1254, 1256-1307, 1309-1423


1519-1725: partitionByNewLine semantics validated.

Good check that sorting occurs within, not across, blank-line partitions.

rules/sort-decorators.ts (5)

4-7: Type centralization LGTM.

Moving public types into rules/sort-decorators/types reduces duplication and drift across files.


70-131: Meta/schema and messages look consistent.

  • New options (partitionByNewLine/newlinesBetween) are correctly exposed in the schema.
  • Messages map aligns with the renamed public IDs.

142-142: Good guard on mutually exclusive newline options.

The explicit validation prevents ambiguous configurations at runtime.


274-280: Tests cover all new message IDs. Verified that missedSpacingBetweenDecorators, extraSpacingBetweenDecorators, unexpectedDecoratorsGroupOrder, and unexpectedDecoratorsOrder are referenced throughout test/rules/sort-decorators.test.ts.


169-176: AccessorProperty is supported by current parser version
@typescript-eslint/parser v8.39.0 includes AST_NODE_TYPES.AccessorProperty (introduced in v7.16.0), so this listener will fire as intended. (newreleases.io)

Comment on lines 352 to 359
interface CustomGroupDefinition {
groupName: string
type?: 'alphabetical' | 'natural' | 'line-length' | 'unsorted'
order?: 'asc' | 'desc'
fallbackSort?: { type: string; order?: 'asc' | 'desc' }
newlinesInside?: number
selector?: string
elementNamePattern?: string | string[] | { pattern: string; flags?: string } | { pattern: string; flags?: string }[]
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Correct CustomGroupDefinition typings (fallbackSort, newlinesInside).

Align with runtime/types: fallbackSort type union; newlinesInside supports 'always' | 'never' | number.

 interface CustomGroupDefinition {
   groupName: string
   type?: 'alphabetical' | 'natural' | 'line-length' | 'unsorted'
   order?: 'asc' | 'desc'
-  fallbackSort?: { type: string; order?: 'asc' | 'desc' }
-  newlinesInside?: number
+  fallbackSort?: {
+    type: 'alphabetical' | 'natural' | 'line-length' | 'custom' | 'unsorted'
+    order?: 'asc' | 'desc'
+  }
+  newlinesInside?: 'always' | 'never' | number
   selector?: string
   elementNamePattern?: string | string[] | { pattern: string; flags?: string } | { pattern: string; flags?: string }[]
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
interface CustomGroupDefinition {
groupName: string
type?: 'alphabetical' | 'natural' | 'line-length' | 'unsorted'
order?: 'asc' | 'desc'
fallbackSort?: { type: string; order?: 'asc' | 'desc' }
newlinesInside?: number
selector?: string
elementNamePattern?: string | string[] | { pattern: string; flags?: string } | { pattern: string; flags?: string }[]
}
interface CustomGroupDefinition {
groupName: string
type?: 'alphabetical' | 'natural' | 'line-length' | 'unsorted'
order?: 'asc' | 'desc'
fallbackSort?: {
type: 'alphabetical' | 'natural' | 'line-length' | 'custom' | 'unsorted'
order?: 'asc' | 'desc'
}
newlinesInside?: 'always' | 'never' | number
selector?: string
elementNamePattern?: string | string[] | { pattern: string; flags?: string } | { pattern: string; flags?: string }[]
}
🤖 Prompt for AI Agents
In docs/content/rules/sort-decorators.mdx around lines 352 to 360, the
CustomGroupDefinition TypeScript example has incorrect typings for fallbackSort
and newlinesInside; update fallbackSort to be a union matching runtime/types
(i.e. allow the same sort descriptor shape or the broader union used at runtime,
not just { type: string; order?: 'asc'|'desc' }), and change newlinesInside to
accept 'always' | 'never' | number instead of only number; adjust the typedef
text accordingly so the docs match the runtime/types definitions.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 9

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (10)
docs/content/rules/sort-array-includes.mdx (1)

250-252: Document the full union for newlinesBetween

Code/types accept 'always' | 'never' | number | 'ignore', but docs list only number | 'ignore'.

-<sub>type: `number | 'ignore'`</sub>
+<sub>type: `'always' | 'never' | number | 'ignore'`</sub>
test/rules/sort-array-includes.test.ts (3)

1183-1199: Fix spread element quoted as a string

'...foo' must be a spread element, not a string literal. This breaks grouping by selector and expected fixes.

-          [
-            '...foo',
-            'cFoo',
-            'a',
-          ].includes(value)
+          [
+            ...foo,
+            'cFoo',
+            'a',
+          ].includes(value)
@@
-          [
-            'a',
-            '...foo',
-            'cFoo',
-          ].includes(value)
+          [
+            'a',
+            ...foo,
+            'cFoo',
+          ].includes(value)

2980-2997: Fix spread element quoted as a string (natural block)

Same issue as above.

-          [
-            '...foo',
-            'cFoo',
-            'a',
-          ].includes(value)
+          [
+            ...foo,
+            'cFoo',
+            'a',
+          ].includes(value)
@@
-          [
-            'a',
-            '...foo',
-            'cFoo',
-          ].includes(value)
+          [
+            'a',
+            ...foo,
+            'cFoo',
+          ].includes(value)

4756-4768: Fix spread element quoted as a string (line-length block)

Same issue as above.

-          [
-            '...foo',
-            'cFoo',
-            'a',
-          ].includes(value)
+          [
+            ...foo,
+            'cFoo',
+            'a',
+          ].includes(value)
docs/content/rules/sort-heritage-clauses.mdx (1)

321-333: Update example to new array-based customGroups API (object form is no longer supported).

This contradicts the migration note above. Replace the map with an array of definitions.

  {
    groups: [
      'withIdInterface',         // [!code ++]
      'unknown'
    ],
-+  customGroups: {              // [!code ++]
-+
-+    withIdInterface: '^WithId' // [!code ++]
-+  }                            // [!code ++]
+   customGroups: [              // [!code ++]
+     {                          // [!code ++]
+       groupName: 'withIdInterface',
+       elementNamePattern: '^WithId'
+     }
+   ]                            // [!code ++]
  }
docs/content/rules/sort-decorators.mdx (1)

272-276: Document full groups union shape.

Schema allows objects between groups (newlinesBetween/commentAbove). Update the type and inline example.

-<sub>
-  type: `Array<string | string[]>`
-</sub>
+<sub>
+  type: `Array<string | string[] | { newlinesBetween: 'always' | 'never' | number | 'ignore'; commentAbove?: string }>`
+</sub>

Also rename “See the groups option” anchor to match the section header or keep as-is if correct.

Also applies to: 293-311

rules/sort-object-types.ts (1)

379-399: Use definite indices instead of .at(...) to satisfy TS and avoid undefined.

range.at(0) and range.at(1) are typed as possibly undefined; this can break under strict TS configs. Use indexed access.

-      let end: number =
-        typeElement.typeAnnotation?.range.at(0) ??
-        typeElement.range.at(1)! - (typeElement.optional ? '?'.length : 0)
-      name = sourceCode.text.slice(typeElement.range.at(0), end)
+      let end: number =
+        typeElement.typeAnnotation?.range[0] ??
+        typeElement.range[1] - (typeElement.optional ? '?'.length : 0)
+      name = sourceCode.text.slice(typeElement.range[0], end)
@@
-    let endIndex: number =
-      typeElement.typeAnnotation?.range.at(0) ?? typeElement.range.at(1)!
+    let endIndex: number =
+      typeElement.typeAnnotation?.range[0] ?? typeElement.range[1]
@@
-    name = formatName(
-      sourceCode.text.slice(typeElement.range.at(0), typeElement.range.at(1)),
-    )
+    name = formatName(
+      sourceCode.text.slice(typeElement.range[0], typeElement.range[1]),
+    )
docs/content/rules/sort-intersection-types.mdx (2)

231-244: Fix mismatched quotes in selector names.

Backticks slipped into the quoted selector literals; renderers will show them incorrectly.

Apply:

- - `'conditional`' — Conditional types.
- - `'function`' — Function types.
- - `'import`' — Imported types.
- - `'intersection`' — Intersection types.
- - `'keyword`' — Keyword types.
- - `'literal`' — Literal types.
- - `'named`' — Named types.
- - `'object`' — Object types.
- - `'operator`' — Operator types.
- - `'tuple`' — Tuple types.
- - `'union`' — Union types.
- - `'nullish`' — Nullish types (`null` or `undefined`).
- - `'unknown`' — Types that don’t fit into any group specified in the `groups` option.
+ - `'conditional'` — Conditional types.
+ - `'function'` — Function types.
+ - `'import'` — Imported types.
+ - `'intersection'` — Intersection types.
+ - `'keyword'` — Keyword types.
+ - `'literal'` — Literal types.
+ - `'named'` — Named types.
+ - `'object'` — Object types.
+ - `'operator'` — Operator types.
+ - `'tuple'` — Tuple types.
+ - `'union'` — Union types.
+ - `'nullish'` — Nullish types (`null` or `undefined`).
+ - `'unknown'` — Types that don’t fit into any group specified in the `groups` option.

490-491: Update incorrect "Test source" link in docs

docs/content/rules/sort-intersection-types.mdx (lines 490–491): 'Rule source' link is correct; change 'Test source' from
https://github.com/azat-io/eslint-plugin-perfectionist/blob/main/test/sort-intersection-types.test.ts
to
https://github.com/azat-io/eslint-plugin-perfectionist/blob/main/test/rules/sort-intersection-types.test.ts

package.json (1)

20-23: Alphabet types path does not match emitted structure.

Exports map "./alphabet".types to ./dist/alphabet.d.ts while JS points to ./dist/utils/alphabet.js. With preserveModules and current includes, the d.ts will land under dist/utils/alphabet.d.ts, not at the root. This breaks TS resolution for consumers.

Apply one of:

  • Fix exports to point to ./dist/utils/alphabet.d.ts (simplest), or
  • Change Vite/dts config to emit alphabet.d.ts at root (more complex).

Patch (exports fix):

     "./alphabet": {
-      "types": "./dist/alphabet.d.ts",
+      "types": "./dist/utils/alphabet.d.ts",
       "default": "./dist/utils/alphabet.js"
     },
♻️ Duplicate comments (9)
test/rules/sort-sets.test.ts (2)

1761-1763: Same change here — looks good

Mirrors the alphabetical suite updates.

Also applies to: 1769-1775, 1779-1784


3283-3285: Same change here — looks good

Consistent group-aware assertions across suites.

Also applies to: 3291-3297, 3301-3306

docs/content/rules/sort-decorators.mdx (2)

255-263: Fix newlinesBetween type and values.

Must include 'always' and 'never' to match runtime/schema.

-<sub>type: `number | 'ignore'`</sub>
+<sub>type: `'always' | 'never' | number | 'ignore'`</sub>
 <sub>default: `'ignore'`</sub>

-Specifies how to handle newlines between groups.
+Specifies how to handle newlines between groups.

-- `'ignore'` — Do not report errors related to newlines.
-- `0` — No newlines are allowed.
-- Any other number — Enforce this number of newlines between each group, and forbid newlines inside groups.
+- `'ignore'` — Do not report errors related to newlines.
+- `'always'` — Exactly one blank line between groups.
+- `'never'` — No blank lines between groups.
+- `0` — No blank lines between groups.
+- Any other number — Enforce this exact number of blank lines between groups; forbid blank lines inside groups.

342-349: Correct CustomGroupDefinition/AnyOf typings (fallbackSort, newlinesInside).

Align with rule/types: fallbackSort union and newlinesInside string | number.

 interface CustomGroupDefinition {
   groupName: string
   type?: 'alphabetical' | 'natural' | 'line-length' | 'unsorted'
   order?: 'asc' | 'desc'
-  fallbackSort?: { type: string; order?: 'asc' | 'desc' }
-  newlinesInside?: number
+  fallbackSort?: {
+    type: 'alphabetical' | 'natural' | 'line-length' | 'custom' | 'unsorted'
+    order?: 'asc' | 'desc'
+  }
+  newlinesInside?: 'always' | 'never' | number
   elementNamePattern?: string | string[] | { pattern: string; flags?: string } | { pattern: string; flags?: string }[]
 }
 
 interface CustomGroupAnyOfDefinition {
   groupName: string
   type?: 'alphabetical' | 'natural' | 'line-length' | 'unsorted'
   order?: 'asc' | 'desc'
-  fallbackSort?: { type: string; order?: 'asc' | 'desc' }
-  newlinesInside?: number
+  fallbackSort?: {
+    type: 'alphabetical' | 'natural' | 'line-length' | 'custom' | 'unsorted'
+    order?: 'asc' | 'desc'
+  }
+  newlinesInside?: 'always' | 'never' | number
   anyOf: Array<{
     selector?: string
     elementNamePattern?: string | string[] | { pattern: string; flags?: string } | { pattern: string; flags?: string }[]
   }>
 }

Also applies to: 351-361, 366-378

test/rules/sort-named-imports.test.ts (2)

1860-1866: Same change pattern as above

Group-order assertions and config look consistent for the natural sort suite.

Also applies to: 1911-1912


3371-3377: Same change pattern as above

Group-order assertions and config look consistent for the line-length suite.

Also applies to: 3422-3423

test/rules/sort-named-exports.test.ts (2)

1486-1492: Same change pattern as above

Config and expectations look consistent for the natural sort suite.

Also applies to: 1537-1538


2856-2862: Same change pattern as above

Config and expectations look consistent for the line-length suite.

Also applies to: 2907-2908

vite.config.ts (1)

10-12: Replace import.meta.dirname with an ESM-safe __dirname (Node 20 compatibility).

import.meta.dirname isn’t available in Node 20. This will break the build given engines: "^20.0.0 || >=22.0.0". Use an ESM-safe __dirname shim.

 import path from 'node:path'
+import { fileURLToPath } from 'node:url'
+
+// ESM-safe __dirname
+const __dirname = path.dirname(fileURLToPath(import.meta.url))

-        path.resolve(import.meta.dirname, 'index.ts'),
-        path.resolve(import.meta.dirname, 'utils', 'alphabet.ts'),
+        path.resolve(__dirname, 'index.ts'),
+        path.resolve(__dirname, 'utils', 'alphabet.ts'),
@@
-      include: [
-        path.join(import.meta.dirname, 'index.ts'),
-        path.join(import.meta.dirname, 'types'),
-        path.join(import.meta.dirname, 'rules'),
-        path.join(import.meta.dirname, 'utils'),
-      ],
+      include: [
+        path.join(__dirname, 'index.ts'),
+        path.join(__dirname, 'types'),
+        path.join(__dirname, 'rules'),
+        path.join(__dirname, 'utils'),
+      ],

Also applies to: 29-32

🧹 Nitpick comments (33)
test/rules/sort-sets.test.ts (5)

978-984: Use an actual spread element instead of the string '...foo'

This test is meant to demonstrate anyOf with selector: 'spread', but it currently uses a string literal. Update both code and output to exercise a real spread.

-          new Set([
-            '...foo',
-            'cFoo',
-            'a',
-          ])
+          new Set([
+            ...foo,
+            'cFoo',
+            'a',
+          ])
@@
-          new Set([
-            'a',
-            '...foo',
-            'cFoo',
-          ])
+          new Set([
+            'a',
+            ...foo,
+            'cFoo',
+          ])

Also applies to: 985-991


2500-2506: Same spread-vs-string issue in “natural” anyOf test

Switch to real spread usage to cover the spread selector.

-          new Set([
-            '...foo',
-            'cFoo',
-            'a',
-          ])
+          new Set([
+            ...foo,
+            'cFoo',
+            'a',
+          ])
@@
-          new Set([
-            'a',
-            '...foo',
-            'cFoo',
-          ])
+          new Set([
+            'a',
+            ...foo,
+            'cFoo',
+          ])

Also applies to: 2507-2513


4022-4028: Same spread-vs-string issue in “line-length” anyOf test

Update to actual spread to validate anyOf with selector: 'spread'.

-          new Set([
-            '...foo',
-            'cFoo',
-            'a',
-          ])
+          new Set([
+            ...foo,
+            'cFoo',
+            'a',
+          ])
@@
-          new Set([
-            'a',
-            '...foo',
-            'cFoo',
-          ])
+          new Set([
+            'a',
+            ...foo,
+            'cFoo',
+          ])

Also applies to: 4029-4035


1052-1052: Regex precedence bug: anchor each alternative

'^r|g|b$' means “starts with r” OR “contains g” OR “ends with b”. You likely want exact match for r/g/b.

-              allNamesMatchPattern: '^r|g|b$',
+              allNamesMatchPattern: '^(r|g|b)$',

Also applies to: 2574-2574, 4096-4096


4597-4603: Inconsistent Set construction in “custom” suite

new Set('a', 'b', ...) constructs from only the first iterable argument; others are ignored. Use an array literal for clarity and consistency with the rule’s target shape.

-          new Set(
-            'a',
-            'b',
-            'c',
-            'd',
-          )
+          new Set([
+            'a',
+            'b',
+            'c',
+            'd',
+          ])
rules/sort-exports.ts (1)

151-163: Minor: hoist getOptionsByGroupIndex to avoid recreating per call.

reportAllErrors calls sortNodesExcludingEslintDisabled twice; hoisting saves a closure allocation and makes intent clearer.

       'Program:exit': () => {
-        function sortNodesExcludingEslintDisabled(
+        const getOptionsByGroupIndex =
+          buildGetCustomGroupOverriddenOptionsFunction(options)
+
+        function sortNodesExcludingEslintDisabled(
           ignoreEslintDisabledNodes: boolean,
         ): SortExportsSortingNode[] {
-          return formattedMembers.flatMap(groupedNodes =>
+          return formattedMembers.flatMap(groupedNodes =>
             sortNodesByGroups({
-              getOptionsByGroupIndex:
-                buildGetCustomGroupOverriddenOptionsFunction(options),
+              getOptionsByGroupIndex,
               ignoreEslintDisabledNodes,
               groups: options.groups,
               nodes: groupedNodes,
             }),
           )
         }
rules/sort-heritage-clauses/types.ts (1)

33-35: Prefer const for schema map

This object isn’t reassigned; use const to prevent accidental mutation.

-export let singleCustomGroupJsonSchema: Record<string, JSONSchema4> = {
+export const singleCustomGroupJsonSchema: Record<string, JSONSchema4> = {
   elementNamePattern: regexJsonSchema,
 }
docs/content/rules/sort-array-includes.mdx (2)

491-492: Fix “Test source” link path

Tests live under test/rules now.

-- [Test source](https://github.com/azat-io/eslint-plugin-perfectionist/blob/main/test/sort-array-includes.test.ts)
+- [Test source](https://github.com/azat-io/eslint-plugin-perfectionist/blob/main/test/rules/sort-array-includes.test.ts)

4-4: Grammar tweak in shortDescription

“includes” (method name) reads better than “include”.

-shortDescription: Enforce sorted arrays before include method
+shortDescription: Enforce sorted arrays before includes method
rules/sort-heritage-clauses.ts (3)

46-59: Defaults align with new options; minor nit

Setting newlinesBetween: 'ignore' by default is consistent. Consider adding a comment that per-group overrides are only honored when partitionByNewLine is false (mirrors validator).


138-180: Set partitionId per partition (currently always 0)

partitionId is useful for diagnostics/telemetry; populate it with the current partition index.

-  let formattedMembers: SortingNode[][] = [[]]
+  let formattedMembers: SortingNode[][] = [[]]
   for (let heritageClause of heritageClauses) {
@@
-    let sortingNode: SortingNode = {
+    let sortingNode: SortingNode = {
       isEslintDisabled: isNodeEslintDisabled(
         heritageClause,
         eslintDisabledLines,
       ),
       size: rangeToDiff(heritageClause, sourceCode),
       node: heritageClause,
-      partitionId: 0,
+      partitionId: 0,
       group,
       name,
     }
@@
-    if (
+    if (
       shouldPartition({
         lastSortingNode,
         sortingNode,
         sourceCode,
         options,
       })
     ) {
       formattedMembers.push([])
     }
-
-    formattedMembers.at(-1)!.push(sortingNode)
+    let currentPartitionIndex = formattedMembers.length - 1
+    sortingNode.partitionId = currentPartitionIndex
+    formattedMembers.at(-1)!.push(sortingNode)

197-211: Confirm newlinesBetween value resolver is wired

reportAllErrors can emit missed/extra spacing only if it knows the effective newlinesBetween between group pairs. If not already handled inside reportAllErrors, pass a resolver that respects inline group overrides.

Would you like me to propose a small helper to compute the per-pair newlinesBetween from options.groups and options.newlinesBetween?

docs/content/rules/sort-heritage-clauses.mdx (2)

166-182: Clarify numeric domain for newlinesBetween.

Say “non-negative integer” to avoid ambiguity about negatives and decimals.

 - Any other number — Enforce this number of newlines between each group, and forbid newlines inside groups.
+ - Any non-negative integer — Enforce this number of newlines between each group, and forbid newlines inside groups.

227-254: Call out breaking change and cross-check examples below.

  • Explicitly mark this as a v5.0.0 breaking change.
  • Ensure all examples later in the page use the new array form (there’s at least one object-shaped example below).
 <Important title="Migrating from the old API">
-Support for the object-based `customGroups` option has been removed.
+Support for the object-based `customGroups` option has been removed (breaking change in v5.0.0).
@@
-Migrating from the old to the current API is easy:
+Migrating from the old to the current API is easy. Ensure all examples below use the new array form:
rules/sort-decorators.ts (2)

209-257: Partitioning logic: partitionId assignment is 1-based; OK but add a brief comment.

rangeToDiff + shouldPartition pipeline is sound. A small inline comment clarifies intent for future readers.

-      accumulator.at(-1)!.push({
+      // Partition ids are 1-based to simplify downstream grouping logic
+      accumulator.at(-1)!.push({
         ...sortingNode,
         partitionId: accumulator.length,
       })

145-160: Parameter-decorator entrypoint: consider a safer type guard.

The 'in' check on decorator.parent and Identifier → FunctionExpression chain is fine at runtime but brittle for typings. Prefer a reusable isDecoratedParameter helper to narrow safely.

-      Decorator: decorator => {
-        if (!options.sortOnParameters) return
-        if (
-          'decorators' in decorator.parent &&
-          decorator.parent.type === 'Identifier' &&
-          decorator.parent.parent.type === 'FunctionExpression'
-        ) {
+      Decorator: decorator => {
+        if (!options.sortOnParameters) return
+        if (isDecoratedParameter(decorator)) {
           let { decorators } = decorator.parent
           if (decorator !== decorators[0]) return
           sortDecorators(context, options, decorators)
         }
       },

Type guard (add in this file or a utils/types module):

function isDecoratedParameter(
  d: TSESTree.Decorator,
): d is TSESTree.Decorator & { parent: TSESTree.Identifier & { decorators: TSESTree.Decorator[]; parent: TSESTree.FunctionExpression } } {
  let p = d.parent as any
  return !!p && Array.isArray(p.decorators) && p.type === 'Identifier' && p.parent?.type === 'FunctionExpression'
}
test/rules/sort-decorators.test.ts (2)

539-546: Tests intentionally cover deprecated object-form customGroups; align with final decision.

If v5 removes object-form, replace these occurrences with array-form to match docs. If kept as deprecated, keep these tests but mark them as compatibility and update docs accordingly.

Also applies to: 606-615, 970-983, 1890-1894, 2067-2071, 2673-2674, 3500-3506, 3634-3640, 4240-4241, 5201-5207, 6249-6255, 6829-6831


1-17: Duplicate errors helper is clean; consider stronger typing to silence no-unsafe-call in tests.

Static analysis flags “no-unsafe-call” at many template-tag lines (dedent). Add an ESLint override for tests or ensure dedent types resolve.

Suggested repo-level ESLint override:

 // .eslintrc.cjs (or flat config override)
 {
   "overrides": [
     {
       "files": ["**/*.test.ts"],
-      "rules": {}
+      "rules": {
+        "@typescript-eslint/no-unsafe-call": "off"
+      }
     }
   ]
 }

Also applies to: 6989-6997

docs/content/rules/sort-decorators.mdx (4)

247-252: Clarify partitionByNewLine behavior.

It partitions by blank lines and sorts within partitions; current phrasing suggests “do not sort”.

-When `true`, the rule will not sort the decorators if there is an empty line between them.
+When `true`, blank lines create partitions; sorting is applied within each partition only (no reordering across partitions).

314-341: Migration box: soften “removed” wording if runtime still accepts object form.

If schema keeps deprecated object, change “Support … has been removed” to “deprecated; still accepted in v5, removal in v6”. Otherwise keep “removed”.


415-427: Example diff markers are great; minor formatting nit.

Ensure code fence language hint matches JS/TS (currently fine) and remove trailing spaces (if any).


518-520: Fix “Test source” link path.

The file lives at test/rules/sort-decorators.test.ts.

-- [Test source](https://github.com/azat-io/eslint-plugin-perfectionist/blob/main/test/sort-decorators.test.ts)
+- [Test source](https://github.com/azat-io/eslint-plugin-perfectionist/blob/main/test/rules/sort-decorators.test.ts)
rules/sort-object-types.ts (2)

260-267: Method “value” is always null; confirm desired behavior for sortBy: "value".

Only TSPropertySignature populates value. In groups configured with sortBy: "value", methods and index signatures will be treated as ignored for that group and retain original order. If you intended fallback sorting for those nodes, drop the group-level ignore and rely on fallbackSort.

Possible change (inside isNodeIgnoredForGroup):

-  if (groupOptions.sortBy === 'value') {
-    return !node.value
-  }
-  return false
+  return false

310-313: Partition ID off-by-one semantics—confirm consumer expectations.

partitionId uses formattedMembers.length (1-based). If downstream assumes 0-based group ids, this will misalign. If 1-based is intentional, consider a short comment to codify the contract.

test/rules/sort-named-imports.test.ts (1)

342-348: LGTM: migrated to explicit groups for type imports

The assertions and config now correctly target the 'type-import' group and expect the new group-order message. Consider adding one extra case that explicitly asserts ordering between 'type-import' and 'value-import' to cover both predefined groups.

Also applies to: 393-394

test/rules/sort-named-exports.test.ts (1)

116-122: LGTM: explicit 'type-export' grouping and message id

Tests align with the new groups API and the group-order message. Consider mirroring one case that asserts relative order vs value exports to exercise both predefined groups.

Also applies to: 167-168

docs/content/rules/sort-intersection-types.mdx (6)

11-14: Deduplicate keywords.

"typescript linting" appears twice; keep one.

   - typescript types
-  - typescript linting
   - typescript-eslint

156-156: Grammar: lowercase “to”.

-Refer To
+Refer to

87-87: Wording: “groups” and “newline behavior”.

-- 'unsorted' — Do not sort items. [`grouping`](#groups) and [`newlines behavior`](#newlinesbetween) are still enforced.
+- 'unsorted' — Do not sort items. [`groups`](#groups) and [`newline behavior`](#newlinesbetween) are still enforced.

359-359: Clarify target: not “object type members”.

Here we’re grouping intersection constituents, not object members.

-Defines custom groups to match specific object type members.
+Defines custom groups to match intersection type constituents.

375-375: Grammar and clarity: “A type constituent…”.

-An type member will match a `CustomGroupDefinition` group if it matches all the filters of the custom group's definition.
+A type constituent will match a `CustomGroupDefinition` group if it matches all the filters of the custom group's definition.

393-393: Grammar and clarity: “A type constituent…”.

-An type member will match a `CustomGroupAnyOfDefinition` group if it matches all the filters of at least one of the `anyOf` items.
+A type constituent will match a `CustomGroupAnyOfDefinition` group if it matches all the filters of at least one of the `anyOf` items.
vite.config.ts (1)

27-37: Fix ESLint no-unsafe-call on dts() by ensuring types are resolved.

Lint hints show typescript/no-unsafe-call at Line 27. If TS fails to resolve types for vite-plugin-dts in your setup, explicitly type the plugin or locally suppress the rule for this line.

Option A (typed variable):

-  plugins: [
-    dts({
+  plugins: [
+    (dts({
       include: [
         /* ... */
       ],
       insertTypesEntry: true,
       copyDtsFiles: true,
       strictOutput: true,
-    }),
+    }) as import('vite').PluginOption),

Option B (surgical disable):

-    dts({
+    // eslint-disable-next-line @typescript-eslint/no-unsafe-call
+    dts({
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6008c5f and 7bb92fc.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (36)
  • docs/content/rules/sort-array-includes.mdx (3 hunks)
  • docs/content/rules/sort-decorators.mdx (5 hunks)
  • docs/content/rules/sort-exports.mdx (0 hunks)
  • docs/content/rules/sort-heritage-clauses.mdx (4 hunks)
  • docs/content/rules/sort-interfaces.mdx (0 hunks)
  • docs/content/rules/sort-intersection-types.mdx (1 hunks)
  • docs/content/rules/sort-named-exports.mdx (0 hunks)
  • docs/content/rules/sort-named-imports.mdx (0 hunks)
  • docs/content/rules/sort-object-types.mdx (0 hunks)
  • docs/content/rules/sort-sets.mdx (3 hunks)
  • package.json (5 hunks)
  • rules/sort-array-includes.ts (3 hunks)
  • rules/sort-array-includes/types.ts (0 hunks)
  • rules/sort-decorators.ts (5 hunks)
  • rules/sort-decorators/types.ts (1 hunks)
  • rules/sort-exports.ts (2 hunks)
  • rules/sort-exports/types.ts (0 hunks)
  • rules/sort-heritage-clauses.ts (5 hunks)
  • rules/sort-heritage-clauses/types.ts (1 hunks)
  • rules/sort-interfaces.ts (0 hunks)
  • rules/sort-named-exports.ts (1 hunks)
  • rules/sort-named-exports/types.ts (1 hunks)
  • rules/sort-named-imports.ts (1 hunks)
  • rules/sort-named-imports/types.ts (1 hunks)
  • rules/sort-object-types.ts (1 hunks)
  • rules/sort-object-types/types.ts (0 hunks)
  • test/rules/sort-array-includes.test.ts (12 hunks)
  • test/rules/sort-decorators.test.ts (1 hunks)
  • test/rules/sort-exports.test.ts (0 hunks)
  • test/rules/sort-heritage-clauses.test.ts (1 hunks)
  • test/rules/sort-interfaces.test.ts (0 hunks)
  • test/rules/sort-named-exports.test.ts (6 hunks)
  • test/rules/sort-named-imports.test.ts (6 hunks)
  • test/rules/sort-object-types.test.ts (0 hunks)
  • test/rules/sort-sets.test.ts (3 hunks)
  • vite.config.ts (1 hunks)
💤 Files with no reviewable changes (12)
  • docs/content/rules/sort-exports.mdx
  • rules/sort-interfaces.ts
  • rules/sort-object-types/types.ts
  • docs/content/rules/sort-named-exports.mdx
  • rules/sort-exports/types.ts
  • test/rules/sort-object-types.test.ts
  • docs/content/rules/sort-interfaces.mdx
  • docs/content/rules/sort-object-types.mdx
  • test/rules/sort-interfaces.test.ts
  • rules/sort-array-includes/types.ts
  • test/rules/sort-exports.test.ts
  • docs/content/rules/sort-named-imports.mdx
🚧 Files skipped from review as they are similar to previous changes (4)
  • rules/sort-named-exports/types.ts
  • rules/sort-decorators/types.ts
  • docs/content/rules/sort-sets.mdx
  • rules/sort-array-includes.ts
🧰 Additional context used
🧬 Code graph analysis (8)
rules/sort-heritage-clauses/types.ts (2)
types/common-options.ts (7)
  • CustomGroupsOption (103-140)
  • DeprecatedCustomGroupsOption (473-473)
  • PartitionByCommentOption (288-303)
  • NewlinesBetweenOption (203-226)
  • GroupsOptions (445-451)
  • CommonOptions (23-73)
  • RegexOption (499-499)
utils/common-json-schemas.ts (1)
  • regexJsonSchema (237-246)
rules/sort-named-imports.ts (4)
rules/sort-named-imports/types.ts (1)
  • SortNamedImportsSortingNode (95-95)
utils/sort-nodes-by-groups.ts (1)
  • sortNodesByGroups (106-162)
utils/get-custom-groups-compare-options.ts (1)
  • buildGetCustomGroupOverriddenOptionsFunction (143-154)
utils/report-all-errors.ts (1)
  • reportAllErrors (203-326)
rules/sort-named-imports/types.ts (1)
types/sorting-node.ts (1)
  • SortingNode (18-102)
rules/sort-exports.ts (4)
types/sorting-node.ts (1)
  • SortingNode (18-102)
utils/sort-nodes-by-groups.ts (1)
  • sortNodesByGroups (106-162)
utils/get-custom-groups-compare-options.ts (1)
  • buildGetCustomGroupOverriddenOptionsFunction (143-154)
utils/report-all-errors.ts (1)
  • reportAllErrors (203-326)
rules/sort-named-exports.ts (4)
rules/sort-named-exports/types.ts (1)
  • SortNamedExportsSortingNode (95-95)
utils/sort-nodes-by-groups.ts (1)
  • sortNodesByGroups (106-162)
utils/get-custom-groups-compare-options.ts (1)
  • buildGetCustomGroupOverriddenOptionsFunction (143-154)
utils/report-all-errors.ts (1)
  • reportAllErrors (203-326)
rules/sort-heritage-clauses.ts (11)
rules/sort-heritage-clauses/types.ts (1)
  • Options (15-25)
utils/common-json-schemas.ts (5)
  • buildCustomGroupsArrayJsonSchema (320-369)
  • partitionByNewLineJsonSchema (286-290)
  • partitionByCommentJsonSchema (259-280)
  • newlinesBetweenJsonSchema (146-158)
  • groupsJsonSchema (165-190)
utils/report-errors.ts (4)
  • MISSED_SPACING_ERROR (33-34)
  • EXTRA_SPACING_ERROR (30-31)
  • GROUP_ORDER_ERROR (27-28)
  • ORDER_ERROR (21-22)
utils/validate-newlines-and-partition-configuration.ts (1)
  • validateNewlinesAndPartitionConfiguration (98-119)
types/sorting-node.ts (1)
  • SortingNode (18-102)
utils/compute-group.ts (1)
  • computeGroup (111-163)
utils/does-custom-group-match.ts (1)
  • doesCustomGroupMatch (121-141)
utils/should-partition.ts (1)
  • shouldPartition (69-95)
utils/sort-nodes-by-groups.ts (1)
  • sortNodesByGroups (106-162)
utils/get-custom-groups-compare-options.ts (1)
  • buildGetCustomGroupOverriddenOptionsFunction (143-154)
utils/report-all-errors.ts (1)
  • reportAllErrors (203-326)
rules/sort-object-types.ts (12)
rules/sort-object-types/types.ts (3)
  • SortObjectTypesSortingNode (395-403)
  • Selector (145-150)
  • Modifier (158-158)
utils/is-node-function-type.ts (1)
  • isNodeFunctionType (49-60)
rules/sort-object-types/is-member-optional.ts (1)
  • isMemberOptional (15-23)
utils/generate-predefined-groups.ts (1)
  • generatePredefinedGroups (23-56)
utils/compute-group.ts (1)
  • computeGroup (111-163)
utils/does-custom-group-match.ts (1)
  • doesCustomGroupMatch (121-141)
utils/is-node-eslint-disabled.ts (1)
  • isNodeEslintDisabled (27-32)
utils/range-to-diff.ts (1)
  • rangeToDiff (32-41)
utils/should-partition.ts (1)
  • shouldPartition (69-95)
utils/sort-nodes-by-groups.ts (1)
  • sortNodesByGroups (106-162)
rules/sort-object-types/get-custom-groups-compare-options.ts (1)
  • getCustomGroupsCompareOptions (27-74)
utils/report-all-errors.ts (1)
  • reportAllErrors (203-326)
rules/sort-decorators.ts (6)
rules/sort-decorators/types.ts (1)
  • Options (17-32)
utils/common-json-schemas.ts (6)
  • deprecatedCustomGroupsJsonSchema (192-208)
  • buildCustomGroupsArrayJsonSchema (320-369)
  • partitionByCommentJsonSchema (259-280)
  • partitionByNewLineJsonSchema (286-290)
  • newlinesBetweenJsonSchema (146-158)
  • groupsJsonSchema (165-190)
utils/report-errors.ts (4)
  • MISSED_SPACING_ERROR (33-34)
  • EXTRA_SPACING_ERROR (30-31)
  • GROUP_ORDER_ERROR (27-28)
  • ORDER_ERROR (21-22)
utils/validate-newlines-and-partition-configuration.ts (1)
  • validateNewlinesAndPartitionConfiguration (98-119)
utils/does-custom-group-match.ts (1)
  • doesCustomGroupMatch (121-141)
utils/get-custom-groups-compare-options.ts (1)
  • buildGetCustomGroupOverriddenOptionsFunction (143-154)
🪛 ESLint
test/rules/sort-heritage-clauses.test.ts

[error] 395-395: Unsafe use of a(n) error type typed template tag.

(typescript/no-unsafe-call)


[error] 400-400: Unsafe use of a(n) error type typed template tag.

(typescript/no-unsafe-call)


[error] 446-446: Unsafe use of a(n) error type typed template tag.

(typescript/no-unsafe-call)


[error] 451-451: Unsafe use of a(n) error type typed template tag.

(typescript/no-unsafe-call)


[error] 489-489: Unsafe use of a(n) error type typed template tag.

(typescript/no-unsafe-call)


[error] 494-494: Unsafe use of a(n) error type typed template tag.

(typescript/no-unsafe-call)


[error] 527-527: Unsafe use of a(n) error type typed template tag.

(typescript/no-unsafe-call)


[error] 532-532: Unsafe use of a(n) error type typed template tag.

(typescript/no-unsafe-call)


[error] 554-554: Unsafe use of a(n) error type typed template tag.

(typescript/no-unsafe-call)


[error] 605-605: Unsafe use of a(n) error type typed template tag.

(typescript/no-unsafe-call)


[error] 616-616: Unsafe use of a(n) error type typed template tag.

(typescript/no-unsafe-call)


[error] 675-675: Unsafe use of a(n) error type typed template tag.

(typescript/no-unsafe-call)


[error] 685-685: Unsafe use of a(n) error type typed template tag.

(typescript/no-unsafe-call)


[error] 748-748: Unsafe use of a(n) error type typed template tag.

(typescript/no-unsafe-call)


[error] 761-761: Unsafe use of a(n) error type typed template tag.

(typescript/no-unsafe-call)


[error] 815-815: Unsafe use of a(n) error type typed template tag.

(typescript/no-unsafe-call)


[error] 823-823: Unsafe use of a(n) error type typed template tag.

(typescript/no-unsafe-call)


[error] 873-873: Unsafe use of a(n) error type typed template tag.

(typescript/no-unsafe-call)


[error] 879-879: Unsafe use of a(n) error type typed template tag.

(typescript/no-unsafe-call)


[error] 916-916: Unsafe use of a(n) error type typed template tag.

(typescript/no-unsafe-call)


[error] 944-944: Unsafe use of a(n) error type typed template tag.

(typescript/no-unsafe-call)


[error] 979-979: Unsafe use of a(n) error type typed template tag.

(typescript/no-unsafe-call)


[error] 987-987: Unsafe use of a(n) error type typed template tag.

(typescript/no-unsafe-call)


[error] 1028-1028: Unsafe use of a(n) error type typed template tag.

(typescript/no-unsafe-call)


[error] 1038-1038: Unsafe use of a(n) error type typed template tag.

(typescript/no-unsafe-call)


[error] 1080-1080: Unsafe use of a(n) error type typed template tag.

(typescript/no-unsafe-call)


[error] 1087-1087: Unsafe use of a(n) error type typed template tag.

(typescript/no-unsafe-call)


[error] 1126-1126: Unsafe use of a(n) error type typed template tag.

(typescript/no-unsafe-call)


[error] 1132-1132: Unsafe use of a(n) error type typed template tag.

(typescript/no-unsafe-call)


[error] 1161-1161: Unsafe use of a(n) error type typed template tag.

(typescript/no-unsafe-call)


[error] 1172-1172: Unsafe use of a(n) error type typed template tag.

(typescript/no-unsafe-call)


[error] 1210-1210: Unsafe use of a(n) error type typed template tag.

(typescript/no-unsafe-call)


[error] 1226-1226: Unsafe use of a(n) error type typed template tag.

(typescript/no-unsafe-call)


[error] 1253-1253: Unsafe use of a(n) error type typed template tag.

(typescript/no-unsafe-call)


[error] 1272-1272: Unsafe use of a(n) error type typed template tag.

(typescript/no-unsafe-call)


[error] 1285-1285: Unsafe use of a(n) error type typed template tag.

(typescript/no-unsafe-call)


[error] 1318-1318: Unsafe use of a(n) error type typed template tag.

(typescript/no-unsafe-call)


[error] 1355-1355: Unsafe use of a(n) error type typed template tag.

(typescript/no-unsafe-call)


[error] 1362-1362: Unsafe use of a(n) error type typed template tag.

(typescript/no-unsafe-call)


[error] 1382-1382: Unsafe use of a(n) error type typed template tag.

(typescript/no-unsafe-call)


[error] 1402-1402: Unsafe use of a(n) error type typed template tag.

(typescript/no-unsafe-call)


[error] 1416-1416: Unsafe use of a(n) error type typed template tag.

(typescript/no-unsafe-call)


[error] 1453-1453: Unsafe use of a(n) error type typed template tag.

(typescript/no-unsafe-call)


[error] 1460-1460: Unsafe use of a(n) error type typed template tag.

(typescript/no-unsafe-call)


[error] 1480-1480: Unsafe use of a(n) error type typed template tag.

(typescript/no-unsafe-call)


[error] 1492-1492: Unsafe use of a(n) error type typed template tag.

(typescript/no-unsafe-call)


[error] 1514-1514: Unsafe use of a(n) error type typed template tag.

(typescript/no-unsafe-call)

test/rules/sort-decorators.test.ts

[error] 674-674: Unsafe use of a(n) error type typed template tag.

(typescript/no-unsafe-call)


[error] 701-701: Unsafe use of a(n) error type typed template tag.

(typescript/no-unsafe-call)


[error] 791-791: Unsafe use of a(n) error type typed template tag.

(typescript/no-unsafe-call)


[error] 798-798: Unsafe use of a(n) error type typed template tag.

(typescript/no-unsafe-call)


[error] 829-829: Unsafe use of a(n) error type typed template tag.

(typescript/no-unsafe-call)


[error] 851-851: Unsafe use of a(n) error type typed template tag.

(typescript/no-unsafe-call)


[error] 887-887: Unsafe use of a(n) error type typed template tag.

(typescript/no-unsafe-call)


[error] 929-929: Unsafe use of a(n) error type typed template tag.

(typescript/no-unsafe-call)


[error] 999-999: Unsafe use of a(n) error type typed template tag.

(typescript/no-unsafe-call)


[error] 1089-1089: Unsafe use of a(n) error type typed template tag.

(typescript/no-unsafe-call)


[error] 1099-1099: Unsafe use of a(n) error type typed template tag.

(typescript/no-unsafe-call)


[error] 1157-1157: Unsafe use of a(n) error type typed template tag.

(typescript/no-unsafe-call)


[error] 1166-1166: Unsafe use of a(n) error type typed template tag.

(typescript/no-unsafe-call)


[error] 1228-1228: Unsafe use of a(n) error type typed template tag.

(typescript/no-unsafe-call)


[error] 1240-1240: Unsafe use of a(n) error type typed template tag.

(typescript/no-unsafe-call)


[error] 1293-1293: Unsafe use of a(n) error type typed template tag.

(typescript/no-unsafe-call)


[error] 1300-1300: Unsafe use of a(n) error type typed template tag.

(typescript/no-unsafe-call)


[error] 1349-1349: Unsafe use of a(n) error type typed template tag.

(typescript/no-unsafe-call)


[error] 1354-1354: Unsafe use of a(n) error type typed template tag.

(typescript/no-unsafe-call)


[error] 1390-1390: Unsafe use of a(n) error type typed template tag.

(typescript/no-unsafe-call)


[error] 1416-1416: Unsafe use of a(n) error type typed template tag.

(typescript/no-unsafe-call)


[error] 1450-1450: Unsafe use of a(n) error type typed template tag.

(typescript/no-unsafe-call)


[error] 1457-1457: Unsafe use of a(n) error type typed template tag.

(typescript/no-unsafe-call)


[error] 1497-1497: Unsafe use of a(n) error type typed template tag.

(typescript/no-unsafe-call)


[error] 1506-1506: Unsafe use of a(n) error type typed template tag.

(typescript/no-unsafe-call)


[error] 1547-1547: Unsafe use of a(n) error type typed template tag.

(typescript/no-unsafe-call)


[error] 1553-1553: Unsafe use of a(n) error type typed template tag.

(typescript/no-unsafe-call)


[error] 1591-1591: Unsafe use of a(n) error type typed template tag.

(typescript/no-unsafe-call)


[error] 1596-1596: Unsafe use of a(n) error type typed template tag.

(typescript/no-unsafe-call)


[error] 1608-1608: Unsafe use of a(n) error type typed template tag.

(typescript/no-unsafe-call)


[error] 1655-1655: Unsafe use of a(n) error type typed template tag.

(typescript/no-unsafe-call)

vite.config.ts

[error] 27-27: Unsafe call of a(n) error type typed value.

(typescript/no-unsafe-call)

🔇 Additional comments (23)
test/rules/sort-sets.test.ts (2)

239-241: Groups-based config in partitioned test: LGTM

Adopting groups: ['spread'] matches the new API and keeps the test intent clear.


247-253: Group-aware error assertions: LGTM

Switch to unexpectedSetsGroupOrder with { leftGroup, rightGroup } is correct and aligns with the rule’s new messages.

Also applies to: 256-262

rules/sort-exports.ts (2)

165-179: No change required — newlinesBetweenValueGetter is optional

reportAllErrors declares newlinesBetweenValueGetter as optional (utils/report-all-errors.ts) and uses it via optional chaining (utils/get-newlines-between-errors.ts); many rules (including rules/sort-exports.ts) omit the getter and only rules/sort-classes.ts supplies a custom one. No runtime change required.


50-52: Type alias change LGTM — no stale groupKind usages found.
Dropping groupKind from SortExportsSortingNode aligns with the new groups-based flow.

rules/sort-heritage-clauses/types.ts (1)

15-25: Options shape looks consistent with repo-wide config migration

Unioned customGroups (array and deprecated map), newlines/partition flags, and GroupsOptions wiring LGTM.

test/rules/sort-array-includes.test.ts (1)

1-1: Verify remaining '...' string literals in tests

rg found matches in test/rules/sort-sets.test.ts, test/rules/sort-array-includes.test.ts, and test/rules/sort-maps.test.ts — confirm whether the '...foo' / '...b' entries are intended string literals (expected test data) or accidental "spread-as-string" slips; if accidental, replace with actual spread elements or adjust the expected outputs.

test/rules/sort-heritage-clauses.test.ts (1)

954-996: Great coverage for inline comments + spacing combos

These assertions exercise both missed/extra spacing and comment preservation well.

docs/content/rules/sort-heritage-clauses.mdx (4)

160-166: LGTM: partitionByNewLine description is clear and scoped.

No issues; behavior is described precisely.


206-224: LGTM: per-boundary overrides for newlines are well-explained.

Example and constraints (dependency on partitionByNewLine = false) read correctly.


358-363: LGTM: Flat config shows the new options and empty arrays by default.

Defaults match the Options section.


388-393: LGTM: Legacy config mirrors the flat config example.

Consistent keys and defaults.

rules/sort-decorators.ts (4)

118-131: Nice: public message IDs include spacing variants.

The new missed/extra spacing message IDs map cleanly to shared error templates; consistent with reportAllErrors.


50-68: Sane defaults and ESM-friendly options shape.

Default options align with newlinesBetween/partitionByNewLine validation and array-based customGroups.


132-143: Good guardrail: validateNewlinesAndPartitionConfiguration.

Early validation prevents contradictory newline config and group-level overrides.


259-271: Per-group overrides wired correctly.

buildGetCustomGroupOverriddenOptionsFunction(options) is passed as getOptionsByGroupIndex; matches utils contract.

test/rules/sort-decorators.test.ts (1)

665-752: Great coverage for name patterns, overrides, fallback, unsorted, and newline semantics.

These scenarios exercise the new API surface well and will catch regressions.

Also applies to: 754-806, 808-883, 885-995, 997-1044, 1046-1108, 1110-1177, 1179-1254, 1256-1307, 1309-1423, 1425-1465, 1467-1517, 1606-1725

rules/sort-object-types.ts (1)

298-305: Confirm ShouldPartitionParameters.tokenValueToIgnoreBefore optionality — no action required.
The ShouldPartitionParameters interface in utils/should-partition.ts declares tokenValueToIgnoreBefore?: string, so calling shouldPartition without it is valid.

Likely an incorrect or invalid review comment.

rules/sort-named-exports.ts (1)

168-195: LGTM: unified sorting/reporting pipeline

The extracted sortNodesExcludingEslintDisabled and single reportAllErrors pass improve clarity and keep behavior aligned with other rules.

docs/content/rules/sort-intersection-types.mdx (2)

3-3: Typo fix looks good.

Front-matter description is now clean and accurate.


129-131: Import path verified — keep import { Alphabet } from 'eslint-plugin-perfectionist/alphabet'.

package.json exports include "./alphabet" → ./dist/utils/alphabet.js with types at ./dist/alphabet.d.ts; Alphabet is the exported symbol.

vite.config.ts (1)

8-16: Ignore flattening concern — preserveModules already preserves subpaths.

vite.config.ts sets rollupOptions.output.preserveModules = true and uses lib.fileName((_format, entryName) => ${entryName}.js); with preserveModules Rollup's entry name includes the relative path, so the build will emit dist/utils/alphabet.js matching package.json exports. (rollupjs.org)

Drop name if you don't produce UMD/IIFE builds (it's only required for those formats). (v3.vitejs.dev)

Likely an incorrect or invalid review comment.

package.json (2)

3-3: Version still 4.15.0 while PR targets v5.0.0.

Release scripts tag from package.json. Ensure the version is bumped before running release:* or CI will tag and publish 4.x.

If you bump here:

-  "version": "4.15.0",
+  "version": "5.0.0",

Alternatively, adjust your release tooling to write the new version prior to tagging.


126-127: If ESLint v8 support will be removed in v5.0.0, update the peer range to v9+.

Current state: ./package.json (v4.15.0) has "peerDependencies.eslint": ">=8.45.0"; devDependencies use "eslint": "^9.33.0"; docs/public/llms.txt still says "Compatible with ESLint v8.45.0 or greater"; repository has many "Will be removed in v5.0.0" deprecations but no explicit statement that ESLint v8 will be dropped — confirm the intended policy.

-  "peerDependencies": {
-    "eslint": ">=8.45.0"
-  },
+  "peerDependencies": {
+    "eslint": ">=9.0.0"
+  },

If v8 support is kept temporarily, document that decision in the changelog and update docs/public/llms.txt to avoid surprises.

coderabbitai[bot]

This comment was marked as resolved.

coderabbitai[bot]

This comment was marked as resolved.

coderabbitai[bot]

This comment was marked as resolved.

coderabbitai[bot]

This comment was marked as resolved.

coderabbitai[bot]

This comment was marked as resolved.

coderabbitai[bot]

This comment was marked as resolved.

coderabbitai[bot]

This comment was marked as resolved.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (3)
docs/content/rules/sort-objects.mdx (1)

559-566: customGroups type still shows deprecated map shape

Update the documented type to the new array-based definitions.

-<sub>
-  type: `{ [groupName: string]: string | string[] }`
-</sub>
+<sub>
+  type: `Array<CustomGroupDefinition | CustomGroupAnyOfDefinition>`
+</sub>
rules/sort-object-types/types.ts (2)

161-176: Invalid selector map entry and contradictions for index-signature

  • AllowedModifiersPerSelector includes a multiline selector that doesn’t exist.
  • Declares index-signature: never but elsewhere allows modifiers for index-signature groups.

Remove the phantom selector and keep index-signature with no modifiers.

 interface AllowedModifiersPerSelector {
   /** Property members can be multiline, optional, or required. */
   property: MultilineModifier | OptionalModifier | RequiredModifier

   /** Generic members can be multiline, optional, or required. */
   member: MultilineModifier | OptionalModifier | RequiredModifier

   /** Method members can be multiline, optional, or required. */
   method: MultilineModifier | OptionalModifier | RequiredModifier

-  /** Multiline members can only be optional or required. */
-  multiline: OptionalModifier | RequiredModifier
-
   /** Index signatures cannot have modifiers. */
   'index-signature': never
 }

219-227: IndexSignatureGroup should not include modifiers

Index signatures don’t accept optional/required/multiline modifiers. Limit the group to the selector.

-type IndexSignatureGroup = JoinWithDash<
-  [
-    OptionalModifier,
-    RequiredModifier,
-    MultilineModifier,
-    IndexSignatureSelector,
-  ]
->
+type IndexSignatureGroup = JoinWithDash<[IndexSignatureSelector]>
♻️ Duplicate comments (2)
rules/sort-jsx-props.ts (1)

189-202: Enable spacing diagnostics (missed/extra blank lines).

Pass newlinesBetweenValueGetter so reportAllErrors can evaluate the newlinesBetween option for JSX props.

+import { getLinesBetween } from '../utils/get-lines-between'
@@
       for (let currentNodes of formattedMembers) {
@@
         reportAllErrors<MessageId>({
           availableMessageIds: {
             missedSpacingBetweenMembers: 'missedSpacingBetweenJSXPropsMembers',
             extraSpacingBetweenMembers: 'extraSpacingBetweenJSXPropsMembers',
             unexpectedGroupOrder: 'unexpectedJSXPropsGroupOrder',
             unexpectedOrder: 'unexpectedJSXPropsOrder',
           },
+          newlinesBetweenValueGetter: (left, right) =>
+            getLinesBetween(sourceCode, left, right),
           sortNodesExcludingEslintDisabled:
             createSortNodesExcludingEslintDisabled(currentNodes),
           nodes: currentNodes,
           sourceCode,
           options,
           context,
         })
rules/sort-object-types.ts (1)

328-336: Add newlinesBetweenValueGetter for spacing diagnostics.

The reportAllErrors call is missing the newlinesBetweenValueGetter parameter, which prevents detection of missed/extra blank-line errors when options.newlinesBetween is configured.

Apply this fix:

+ import { getLinesBetween } from '../utils/get-lines-between'

  reportAllErrors<MessageIds>({
    sortNodesExcludingEslintDisabled,
+   newlinesBetweenValueGetter: (left, right) =>
+     getLinesBetween(sourceCode, left, right),
    availableMessageIds,
    sourceCode,
    options,
    context,
    nodes,
  })
🧹 Nitpick comments (10)
docs/content/rules/sort-objects.mdx (1)

334-335: Make flags optional to match RegexOption

flags should be optional (flags?: string) for consistency with other docs and types.

-    declarationCommentMatchesPattern?: string | string[] | { pattern: string; flags: string } | { pattern: string; flags: string }[]
+    declarationCommentMatchesPattern?: string | string[] | { pattern: string; flags?: string } | { pattern: string; flags?: string }[]
rules/sort-object-types/types.ts (1)

331-336: Prefer const for exported constants

Use const for arrays/schemas; avoids accidental reassignment.

-export let allSelectors: Selector[] = [
+export const allSelectors: Selector[] = [
@@
-export let allModifiers: Modifier[] = ['optional', 'required', 'multiline']
+export const allModifiers: Modifier[] = ['optional', 'required', 'multiline']
@@
-export let sortByJsonSchema: JSONSchema4 = {
+export const sortByJsonSchema: JSONSchema4 = {
@@
-export let singleCustomGroupJsonSchema: Record<string, JSONSchema4> = {
+export const singleCustomGroupJsonSchema: Record<string, JSONSchema4> = {

Also applies to: 343-343, 350-353, 365-371

docs/public/llms.txt (1)

13-13: Update ESLint compatibility statement

PR drops ESLint v8; revise to v9+ to avoid confusion.

-- Compatible with ESLint v8.45.0 or greater
+- Compatible with ESLint v9.0.0 or greater
index.ts (2)

71-71: Use const for immutable plugin name

Minor tidy-up.

-let pluginName = 'perfectionist'
+const pluginName = 'perfectionist'

73-101: Avoid double assertion; use satisfies for stronger typing

This keeps type safety without unknown casts.

-let plugin = {
+const plugin = {
   rules: {
     // ...
   },
   meta: {
     version: packageVersion,
     name: packageName,
   },
-} as unknown as ESLint.Plugin
+} satisfies ESLint.Plugin
docs/content/rules/sort-import-attributes.mdx (1)

33-39: Fix line-length preview: show actual length-based order

For shorter-first default, expected order is mode, type, integrity.

   lineLength={dedent`
     import data from 'lib' with {
-      integrity: 'sha256-...',
-      mode: 'no-cors',
-      type: 'json',
+      mode: 'no-cors',
+      type: 'json',
+      integrity: 'sha256-...',
     }
   `}
test/rules/sort-import-attributes.test.ts (2)

821-829: Consider using exact alphabet definition instead of dynamic generation.

The test generates an alphabet dynamically using Alphabet.generateRecommendedAlphabet().sortByLocaleCompare('en-US'), which could lead to non-deterministic behavior if the alphabet generation logic changes. Consider using a fixed alphabet string for more predictable test behavior.

-    let alphabet = Alphabet.generateRecommendedAlphabet()
-      .sortByLocaleCompare('en-US')
-      .getCharacters()
-
-    let options = {
-      type: 'custom',
-      order: 'asc',
-      alphabet,
-    } as const
+    let options = {
+      type: 'custom',
+      order: 'asc',
+      alphabet: 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789', // Or another appropriate fixed alphabet
+    } as const

957-974: Brittle AST mutation test - document the purpose and consider alternatives.

This test mutates the AST to simulate a literal key without a value, which is fragile and could break with parser updates. The test should clearly document why this edge case is important and what real-world scenario it represents.

Consider adding a comment explaining the purpose:

     it('uses the attribute source when a literal key lacks value', async () => {
+      // This test simulates a parser edge case where a literal key's value is undefined
+      // This can occur with certain parser configurations or malformed code
+      // The rule should fall back to using the source text representation in such cases
       function removeLiteralValue(program: TSESTree.Program): void {

Also consider if this edge case could be tested more reliably through a different approach, such as using a fixture file with actual malformed syntax that triggers this condition naturally.

test/rules/sort-object-types.test.ts (1)

2210-2238: Consider consolidating RGB pattern test configurations.

The test defines two separate configurations with allNamesMatchPattern: 'foo' and the actual RGB pattern. The 'foo' configuration appears to be a dummy that will never match. Consider documenting why this dummy configuration is needed or removing it if unnecessary.

           options: [
-            {
-              ...options,
-              useConfigurationIf: {
-                allNamesMatchPattern: 'foo',
-              },
-            },
             {
               ...options,
               customGroups: [
rules/sort-jsx-props/types.ts (1)

130-131: Type alias could be more explicit about custom groups.

The Group type allows any string, which correctly supports custom group names. The documentation could be enhanced to make this clearer.

 /**
  * Represents a group identifier for JSX prop categorization. Can be a
- * predefined group, 'unknown' for uncategorized props, or a custom group name.
+ * predefined group (e.g., 'shorthand-prop', 'multiline-prop'), 'unknown' for 
+ * uncategorized props, or a custom group name defined via customGroups.
  */
 type Group = PropertyGroup | 'unknown' | string
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 73dd08b and 6cdab0e.

📒 Files selected for processing (18)
  • docs/content/rules/sort-import-attributes.mdx (1 hunks)
  • docs/content/rules/sort-interfaces.mdx (3 hunks)
  • docs/content/rules/sort-jsx-props.mdx (3 hunks)
  • docs/content/rules/sort-objects.mdx (4 hunks)
  • docs/public/llms.txt (1 hunks)
  • index.ts (3 hunks)
  • readme.md (1 hunks)
  • rules/sort-import-attributes.ts (1 hunks)
  • rules/sort-import-attributes/types.ts (1 hunks)
  • rules/sort-interfaces.ts (2 hunks)
  • rules/sort-jsx-props.ts (6 hunks)
  • rules/sort-jsx-props/types.ts (4 hunks)
  • rules/sort-object-types.ts (9 hunks)
  • rules/sort-object-types/types.ts (3 hunks)
  • test/rules/sort-import-attributes.test.ts (1 hunks)
  • test/rules/sort-interfaces.test.ts (16 hunks)
  • test/rules/sort-jsx-props.test.ts (35 hunks)
  • test/rules/sort-object-types.test.ts (19 hunks)
✅ Files skipped from review due to trivial changes (1)
  • readme.md
🚧 Files skipped from review as they are similar to previous changes (1)
  • rules/sort-interfaces.ts
🧰 Additional context used
🧬 Code graph analysis (7)
rules/sort-import-attributes.ts (22)
rules/sort-imports.ts (1)
  • MessageId (59-65)
rules/sort-array-includes.ts (1)
  • defaultOptions (60-74)
rules/sort-import-attributes/types.ts (1)
  • Options (45-77)
utils/create-eslint-rule.ts (1)
  • createEslintRule (32-35)
utils/is-sortable.ts (1)
  • isSortable (7-9)
utils/get-settings.ts (1)
  • getSettings (91-136)
utils/complete.ts (1)
  • complete (30-36)
utils/validate-custom-sort-configuration.ts (1)
  • validateCustomSortConfiguration (25-35)
utils/validate-generated-groups-configuration.ts (1)
  • validateGeneratedGroupsConfiguration (74-95)
utils/validate-newlines-and-partition-configuration.ts (1)
  • validateNewlinesAndPartitionConfiguration (98-119)
utils/get-eslint-disabled-lines.ts (1)
  • getEslintDisabledLines (45-97)
types/sorting-node.ts (1)
  • SortingNode (18-102)
utils/compute-group.ts (1)
  • computeGroup (75-113)
utils/does-custom-group-match.ts (1)
  • doesCustomGroupMatch (121-141)
utils/is-node-eslint-disabled.ts (1)
  • isNodeEslintDisabled (27-32)
utils/range-to-diff.ts (1)
  • rangeToDiff (32-41)
utils/should-partition.ts (1)
  • shouldPartition (69-95)
utils/sort-nodes-by-groups.ts (1)
  • sortNodesByGroups (106-162)
utils/get-custom-groups-compare-options.ts (1)
  • buildGetCustomGroupOverriddenOptionsFunction (137-148)
utils/report-all-errors.ts (1)
  • reportAllErrors (203-325)
utils/common-json-schemas.ts (6)
  • commonJsonSchemas (139-140)
  • buildCustomGroupsArrayJsonSchema (302-351)
  • partitionByCommentJsonSchema (241-262)
  • partitionByNewLineJsonSchema (268-272)
  • newlinesBetweenJsonSchema (146-158)
  • groupsJsonSchema (165-190)
utils/report-errors.ts (4)
  • MISSED_SPACING_ERROR (33-34)
  • EXTRA_SPACING_ERROR (30-31)
  • GROUP_ORDER_ERROR (27-28)
  • ORDER_ERROR (21-22)
rules/sort-import-attributes/types.ts (3)
types/common-options.ts (6)
  • RegexOption (477-477)
  • CustomGroupsOption (103-140)
  • PartitionByCommentOption (288-303)
  • NewlinesBetweenOption (203-226)
  • GroupsOptions (445-451)
  • CommonOptions (23-73)
utils/common-json-schemas.ts (1)
  • regexJsonSchema (219-228)
types/sorting-node.ts (1)
  • SortingNode (18-102)
test/rules/sort-import-attributes.test.ts (2)
utils/alphabet.ts (1)
  • Alphabet (46-467)
test/utils/validate-rule-json-schema.ts (1)
  • validateRuleJsonSchema (8-19)
rules/sort-object-types.ts (3)
utils/common-json-schemas.ts (1)
  • regexJsonSchema (219-228)
utils/filter-options-by-all-names-match.ts (1)
  • filterOptionsByAllNamesMatch (80-94)
utils/filter-options-by-declaration-comment-matches.ts (1)
  • filterOptionsByDeclarationCommentMatches (14-39)
rules/sort-jsx-props.ts (4)
rules/sort-jsx-props/types.ts (1)
  • Options (24-65)
utils/common-json-schemas.ts (1)
  • buildCustomGroupsArrayJsonSchema (302-351)
utils/filter-options-by-all-names-match.ts (1)
  • filterOptionsByAllNamesMatch (80-94)
utils/matches.ts (1)
  • matches (39-60)
rules/sort-object-types/types.ts (3)
types/common-options.ts (3)
  • RegexOption (477-477)
  • CustomGroupsOption (103-140)
  • FallbackSortOption (319-331)
rules/sort-objects/types.ts (1)
  • SingleCustomGroup (128-144)
types/join-with-dash.ts (1)
  • JoinWithDash (4-4)
rules/sort-jsx-props/types.ts (2)
types/common-options.ts (1)
  • CustomGroupsOption (103-140)
rules/sort-object-types/types.ts (3)
  • SingleCustomGroup (114-133)
  • Selector (141-145)
  • allSelectors (331-336)
🔇 Additional comments (41)
docs/content/rules/sort-objects.mdx (3)

353-366: Good: array-based customGroups example aligns with new API

Example correctly shows groupName + elementNamePattern.


398-416: Good: clear example for declarationCommentMatchesPattern

Docs and example are consistent.


752-754: Broken test link path

Tests live under test/rules/… now. Adjust link.

-- [Test source](https://github.com/azat-io/eslint-plugin-perfectionist/blob/main/test/sort-objects.test.ts)
+- [Test source](https://github.com/azat-io/eslint-plugin-perfectionist/blob/main/test/rules/sort-objects.test.ts)
rules/sort-object-types/types.ts (4)

35-40: Addition of declarationCommentMatchesPattern looks good

Option shape matches RegexOption usage.


58-65: Per‑group fallbackSort extension is reasonable

Typing extension for fallbackSort with sortBy is consistent with global option.


235-238: PropertyGroup introduction is consistent

Matches the other selector groups’ pattern.


380-389: Sorting node shape LGTM

value for type-annotation text is appropriate; nullable is correct.

docs/public/llms.txt (2)

17-26: Good: link hygiene to canonical docs

Updated URLs look correct.


30-50: Good: new rule listed

sort-import-attributes entry added consistently with others.

index.ts (1)

6-6: Rule wiring for sort-import-attributes is correct

Import, typing, and rules map entry are all present.

Please confirm the file exists at rules/sort-import-attributes.ts and is exported as default.

Also applies to: 31-31, 77-77

docs/content/rules/sort-import-attributes.mdx (2)

146-157: newlinesBetween semantics clearly described

Matches rule behavior; no changes needed.


268-275: Version and resources look right

Intro version and paths align with the new rule.

docs/content/rules/sort-jsx-props.mdx (1)

269-283: LGTM! Clear migration from object to array-based customGroups API.

The documentation clearly shows the migration path from the deprecated object-based API to the new array-based format, making it easy for users to update their configurations.

rules/sort-import-attributes/types.ts (1)

16-31: Well-structured type definitions for import attributes sorting.

The SingleCustomGroup interface and related types are well-documented with clear JSDoc comments explaining their purpose. The type definitions properly leverage existing common types and schemas from the codebase.

test/rules/sort-object-types.test.ts (2)

252-253: Good adaptation to new member-based terminology.

The test correctly updates group names from optional-multiline to optional-multiline-member, maintaining consistency with the new naming convention across the codebase.

Also applies to: 261-262


2370-2425: Excellent test coverage for the new declarationCommentMatchesPattern feature.

The test thoroughly validates that type declarations with matching comments can skip sorting, providing good coverage for both positive and negative cases.

docs/content/rules/sort-interfaces.mdx (2)

375-394: Clear documentation for the new declarationCommentMatchesPattern option.

The documentation provides a clear example showing how to skip sorting for interfaces with specific comments, which is a useful feature for gradual migration or special cases.


330-343: LGTM! Clear array-based customGroups example.

The RGB color sorting example effectively demonstrates the new array-based customGroups API with proper groupName and elementNamePattern properties.

test/rules/sort-interfaces.test.ts (2)

2320-2349: LGTM! Clean migration to array-based customGroups.

The test correctly demonstrates the new array-based API with elementNamePattern and groupName fields. The multi-configuration approach with allNamesMatchPattern filtering is well-tested.


2442-2497: Good addition: Test coverage for declaration comment matching.

The new test validates the declarationCommentMatchesPattern filter, which is an important pattern-matching feature. The test properly demonstrates both matching and non-matching scenarios.

rules/sort-import-attributes.ts (2)

39-44: Consider using a dedicated type for import attributes message IDs.

The MessageId type is locally defined but follows the same pattern as other rules. For consistency with the broader codebase, this is appropriate.


203-212: LGTM! Robust attribute name extraction.

The getAttributeName function properly handles both Identifier and Literal key types with a sensible fallback to source text.

rules/sort-jsx-props/types.ts (1)

113-117: LGTM! Documentation updated to reflect selector constraints.

The JSDoc comment has been properly updated to reflect that only 'prop' is a valid selector, addressing the previous concern about stale documentation.

test/rules/sort-jsx-props.test.ts (11)

203-204: LGTM! Consistent renaming of shorthand groups.

The change from 'unknown', 'shorthand' to 'unknown', 'shorthand-prop' properly aligns with the new naming convention for predefined groups.


224-225: LGTM! Error data updated for new group names.

The error expectations correctly reflect the renamed groups ('shorthand-prop' instead of 'shorthand').


259-259: LGTM! Multiline groups renamed consistently.

The multiline options now use 'multiline-prop' instead of 'multiline', maintaining consistency with the new naming pattern.


284-285: LGTM! Error data reflects multiline group renaming.

The error expectations correctly use the new 'multiline-prop' group name.


329-334: LGTM! CustomGroups migrated to array-based API.

The migration from object-based customGroups to array-based GroupDefinition objects is implemented correctly. The new structure with elementNamePattern and groupName properties aligns with the ESM changes.


867-872: LGTM! Multiple customGroups example updated.

The test correctly demonstrates creating multiple custom groups using the array-based API.


1187-1199: LGTM! Test preserves inline comments with new API.

The test correctly uses the new array-based customGroups structure while validating comment preservation during reordering.


1239-1267: LGTM! useConfigurationIf tests updated for new structure.

The conditional configuration tests properly demonstrate the new array-based options structure with multiple configurations filtered by useConfigurationIf.


2866-2867: LGTM! Line-length sort tests updated consistently.

All line-length sorting tests correctly use the renamed groups (shorthand-prop, multiline-prop) and the array-based customGroups API.

Also applies to: 2922-2923, 2998-3005


4118-4133: LGTM! Unsorted type tests properly migrated.

The unsorted type tests correctly demonstrate the array-based customGroups structure while preserving element order within groups.


1538-1539: Verify test coverage for all renamed groups.

While the tests cover shorthand-prop and multiline-prop, ensure all predefined group renamings are tested across different sort types.

Also applies to: 1594-1595, 1659-1672

rules/sort-object-types.ts (7)

67-82: LGTM! Default options properly updated for array-based customGroups.

The change from customGroups: {} to customGroups: [] correctly reflects the migration to array-based custom groups. The typing update to Required<Options[number]> is also appropriate.


94-95: LGTM! JSON schema supports declarationCommentMatchesPattern.

The addition of declarationCommentMatchesPattern to the schema enables comment-based configuration filtering.


98-101: LGTM! CustomGroups schema migrated to array builder.

The migration to buildCustomGroupsArrayJsonSchema with fallback sort properties aligns with the ESM changes.


125-126: LGTM! Parent node tracking improved.

Passing the actual parent node instead of just the name enables richer pattern matching and comment-based filtering.


177-182: LGTM! Context matching logic extracted and enhanced.

The new computeMatchedContextOptions helper centralizes option filtering logic and supports both name-based and comment-based matching.


197-293: LGTM! Sorting logic refactored to 2D array approach.

The refactoring from reduce-based formatting to a 2D array with explicit partition handling is cleaner and more maintainable. The logic correctly:

  • Skips call and construct signatures
  • Assigns appropriate selectors and modifiers
  • Handles partitioning based on newlines/comments
  • Builds sorting nodes with proper group assignment

382-426: LGTM! Comprehensive context matching implementation.

The computeMatchedContextOptions function properly implements the filtering pipeline:

  1. Filters by all names matching pattern
  2. Filters by declaration comment matching pattern
  3. Checks declaration name pattern

This enables flexible configuration selection based on multiple criteria.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (6)
docs/content/rules/sort-objects.mdx (1)

559-562: Fix customGroups type: object map is deprecated in v5; docs should show array form

The section still documents the old object-map shape. Update the type to the new array-based API to avoid misconfiguration.

-<sub>
-  type: `{ [groupName: string]: string | string[] }`
-</sub>
+<sub>
+  type: `Array<CustomGroupDefinition | CustomGroupAnyOfDefinition>`
+</sub>
docs/content/rules/sort-jsx-props.mdx (1)

303-307: Invalid regex example: leading '*' is not valid

Use a proper wildcard.

-        tagMatchesPattern: '*Component$',
+        tagMatchesPattern: '.*Component$',
rules/sort-object-types/types.ts (2)

219-226: Do not allow modifiers on index-signature in Group type.

Index signatures can’t be optional/required/multiline; type should not synthesize such groups.

-type IndexSignatureGroup = JoinWithDash<
-  [
-    OptionalModifier,
-    RequiredModifier,
-    MultilineModifier,
-    IndexSignatureSelector,
-  ]
->
+type IndexSignatureGroup = 'index-signature'

171-176: Remove stale 'multiline' selector entry from AllowedModifiersPerSelector.

There’s no Multiline selector anymore; keeping it is misleading.

 interface AllowedModifiersPerSelector {
   /** Property members can be multiline, optional, or required. */
   property: MultilineModifier | OptionalModifier | RequiredModifier
   /** Generic members can be multiline, optional, or required. */
   member: MultilineModifier | OptionalModifier | RequiredModifier
   /** Method members can be multiline, optional, or required. */
   method: MultilineModifier | OptionalModifier | RequiredModifier
-  /** Multiline members can only be optional or required. */
-  multiline: OptionalModifier | RequiredModifier
   /** Index signatures cannot have modifiers. */
   'index-signature': never
 }
test/rules/sort-interfaces.test.ts (1)

2589-2601: Fix invalid index-signature syntax in tests

Replace bare index-signature entries with a typed index signature — TypeScript requires a colon and type.

Locations: test/rules/sort-interfaces.test.ts — lines 2591, 2598, 5166, 5173

-            [key: string]
+            [key: string]: string
test/rules/sort-jsx-props.test.ts (1)

15-22: Move parser to languageOptions.parser (not inside parserOptions).

languageOptions.parser must be set to the parser itself (typescriptParser); it's currently nested inside languageOptions.parserOptions and will be ignored.
File: test/rules/sort-jsx-props.test.ts (createRuleTester languageOptions block).

Apply:

-      parserOptions: {
-        tsconfigRootDir: path.join(import.meta.dirname, '../fixtures'),
-        extraFileExtensions: ['.svelte', '.astro', '.vue'],
-        ecmaFeatures: { jsx: true },
-        project: './tsconfig.json',
-        parser: typescriptParser,
-      },
+      parser: typescriptParser,
+      parserOptions: {
+        tsconfigRootDir: path.join(import.meta.dirname, '../fixtures'),
+        extraFileExtensions: ['.svelte', '.astro', '.vue'],
+        ecmaFeatures: { jsx: true },
+        project: './tsconfig.json',
+      },
♻️ Duplicate comments (4)
rules/sort-jsx-props/types.ts (1)

100-104: Stale JSDoc: only 'prop' selector is supported; use modifiers for specificity

The comment still lists 'multiline'/'shorthand' as selectors, which contradicts the types/schema.

-  /**
-   * The selector type for this group. Can be 'prop' for regular props,
-   * 'multiline' for multi-line props, or 'shorthand' for shorthand props.
-   */
+  /**
+   * Selector for this group. Allowed: 'prop' only.
+   * Use modifiers ('shorthand' | 'multiline') to target those cases.
+   */
rules/sort-object-types.ts (2)

234-238: Don’t assign optional/required to index signatures.

Index signatures aren’t optional/required; adding these modifiers creates misleading groups (e.g., required-index-signature).

-    if (isMemberOptional(typeElement)) {
-      modifiers.push('optional')
-    } else {
-      modifiers.push('required')
-    }
+    if (typeElement.type !== 'TSIndexSignature') {
+      if (isMemberOptional(typeElement)) {
+        modifiers.push('optional')
+      } else {
+        modifiers.push('required')
+      }
+    }

328-337: Enable spacing diagnostics: pass newlinesBetweenValueGetter.

Without it, missed/extra blank‑line messages won’t be reported when newlinesBetween is set.

 import { reportAllErrors } from '../utils/report-all-errors'
+import { getLinesBetween } from '../utils/get-lines-between'
 ...
   reportAllErrors<MessageIds>({
     sortNodesExcludingEslintDisabled,
+    newlinesBetweenValueGetter: (left, right) =>
+      getLinesBetween(sourceCode, left, right),
     availableMessageIds,
     sourceCode,
     options,
     context,
     nodes,
   })
rules/sort-import-attributes.ts (1)

149-162: Missing newlinesBetweenValueGetter in reportAllErrors call.

Based on the past review comments and the reportAllErrors function signature in the relevant code snippets, the call is missing the newlinesBetweenValueGetter parameter which is required for spacing diagnostics to work correctly.

Looking at the utils/report-all-errors.ts code, the function expects a newlinesBetweenValueGetter parameter. Add the missing parameter:

+import { getLinesBetween } from '../utils/get-lines-between'
@@
         reportAllErrors<MessageId>({
           availableMessageIds: {
             missedSpacingBetweenMembers: 'missedSpacingBetweenImportAttributes',
             extraSpacingBetweenMembers: 'extraSpacingBetweenImportAttributes',
             unexpectedGroupOrder: 'unexpectedImportAttributesGroupOrder',
             unexpectedOrder: 'unexpectedImportAttributesOrder',
           },
+          newlinesBetweenValueGetter: (left, right) =>
+            getLinesBetween(sourceCode, left, right),
           sortNodesExcludingEslintDisabled:
             createSortNodesExcludingEslintDisabled(nodes),
           sourceCode,
           options,
           context,
           nodes,
         })
🧹 Nitpick comments (24)
docs/content/rules/sort-objects.mdx (2)

368-369: Tighten regex example for allNamesMatchPattern

Use a grouped alternation to match exactly r|g|b.

-        allNamesMatchPattern: '^r|g|b$',
+        allNamesMatchPattern: '^(?:r|g|b)$',

235-235: Minor copy: “Refer to”

Lowercase “to”.

-Specifies the sorting locales. Refer To
+Specifies the sorting locales. Refer to
rules/sort-jsx-props/types.ts (1)

146-153: Prefer const over let for immutable tables

These exports are constant lookup tables; make them const.

-export let allSelectors: Selector[] = ['prop']
+export const allSelectors: Selector[] = ['prop'] as const
@@
-export let allModifiers: Modifier[] = ['shorthand', 'multiline']
+export const allModifiers: Modifier[] = ['shorthand', 'multiline'] as const
@@
-export let singleCustomGroupJsonSchema: Record<string, JSONSchema4> = {
+export const singleCustomGroupJsonSchema: Record<string, JSONSchema4> = {

Also applies to: 158-163

rules/sort-interfaces.ts (1)

20-20: Use const for defaultOptions

Avoid accidental mutation.

-let defaultOptions: Required<Options[number]> = {
+const defaultOptions: Required<Options[number]> = {
test/rules/sort-object-types.test.ts (1)

2199-2206: Regex precision: anchor the whole token with a grouped alternation

'^r|g|b$' can match unintended names. Use '^(?:r|g|b)$' (and same for the case-insensitive variant).

-      ['string pattern', '^r|g|b$'],
+      ['string pattern', '^(?:r|g|b)$'],
@@
-      ['regex pattern', { pattern: '^R|G|B$', flags: 'i' }],
+      ['regex pattern', { pattern: '^(?:R|G|B)$', flags: 'i' }],

Repeat the same change in the natural and line-length suites.

Also applies to: 4767-4774, 7278-7285

docs/content/rules/sort-interfaces.mdx (2)

309-315: Make flags optional in Regex-like option types (keep docs consistent with code).

Docs show flags as required; types use optional flags. Update the type block.

   {
-    allNamesMatchPattern?: string | string[] | { pattern: string; flags: string } | { pattern: string; flags: string }[]
-    declarationMatchesPattern?: string | string[] | { pattern: string; flags: string } | { pattern: string; flags: string }[]
-    declarationCommentMatchesPattern?: string | string[] | { pattern: string; flags: string } | { pattern: string; flags: string }[]
+    allNamesMatchPattern?: string | string[] | { pattern: string; flags?: string } | { pattern: string; flags?: string }[]
+    declarationMatchesPattern?: string | string[] | { pattern: string; flags?: string } | { pattern: string; flags?: string }[]
+    declarationCommentMatchesPattern?: string | string[] | { pattern: string; flags?: string } | { pattern: string; flags?: string }[]
   }

753-755: Fix outdated test link path.

Tests live under test/rules now.

-- [Test source](https://github.com/azat-io/eslint-plugin-perfectionist/blob/main/test/sort-interfaces.test.ts)
+- [Test source](https://github.com/azat-io/eslint-plugin-perfectionist/blob/main/test/rules/sort-interfaces.test.ts)
rules/sort-object-types/types.ts (1)

35-40: Nit: clarify wording (“comment content” rather than “names”).

Docstring mentions “matching names”; consider “matching content” for comment patterns.

test/rules/sort-jsx-props.test.ts (2)

1231-1235: Tighten regex alternation precedence.

Patterns like "^r|g|b$" match more than intended (e.g., any string containing "g"). Prefer grouping.

Apply this diff in each occurrence:

- '^r|g|b$'
+ '^(?:r|g|b)$'

Also applies to: 2566-2570, 3901-3905


15-16: Prefer portable import.meta.url over non‑standard import.meta.dirname.

import.meta.dirname isn’t standard Node ESM. Use fileURLToPath to derive a directory for cross‑runtime robustness.

+import { fileURLToPath } from 'node:url'
+import { dirname } from 'node:path'
 ...
-        tsconfigRootDir: path.join(import.meta.dirname, '../fixtures'),
+        tsconfigRootDir: path.join(
+          dirname(fileURLToPath(import.meta.url)),
+          '../fixtures'
+        ),
rules/sort-export-attributes.ts (4)

63-63: Potential issue: Use more specific type check for attributes

The current check for node.attributes may not be sufficient. Consider checking if attributes exists and is an array to avoid potential runtime errors.

-      let attributes: TSESTree.ImportAttribute[] | undefined = node.attributes
+      let attributes = node.attributes as TSESTree.ImportAttribute[] | undefined

86-86: Fix typo: "import" should be "export" in test comment

The comment references import attributes but this is for export attributes.

-        let name = getAttributeName(attribute, sourceCode)
+        let name = getAttributeName(attribute, sourceCode)

133-147: Consider extracting duplicate sorting logic

This pattern of creating createSortNodesExcludingEslintDisabled is identical to the one in sort-import-attributes.ts. Consider extracting this into a shared utility function to reduce duplication.

Would you like me to help create a shared utility function for this pattern that both rules can use?


39-44: Consider using a shared type for MessageId

The MessageId type follows a similar pattern across sorting rules. Consider creating a shared type builder utility to maintain consistency.

test/rules/sort-import-attributes.test.ts (2)

25-25: Inconsistent test descriptions across sorting modes

Test descriptions use "sorts import attributes" for alphabetical/natural modes but "sorts import attributes" for others. Consider using consistent terminology like "sorts export attributes" throughout.

Also applies to: 276-276, 551-551, 831-831, 862-862


975-993: Consider simplifying the custom parser wrapper

The parser wrapper could be simplified by extracting the common logic into a helper function.

-      let parserWithMissingLiteralValue = {
-        ...typescriptParser,
-        parseForESLint(
-          code: string,
-          parserOptions?: Parameters<typeof typescriptParser.parseForESLint>[1],
-        ) {
-          let result = typescriptParser.parseForESLint(code, parserOptions)
-          removeLiteralValue(result.ast)
-          return result
-        },
-        parse(
-          code: string,
-          parserOptions?: Parameters<typeof typescriptParser.parse>[1],
-        ) {
-          let program = typescriptParser.parse(code, parserOptions)
-          removeLiteralValue(program)
-          return program
-        },
-      }
+      function wrapParser<T extends { ast?: TSESTree.Program } | TSESTree.Program>(
+        parseFn: (...args: any[]) => T,
+      ) {
+        return (...args: Parameters<typeof parseFn>) => {
+          let result = parseFn(...args)
+          let ast = 'ast' in result ? result.ast : result
+          if (ast) removeLiteralValue(ast)
+          return result
+        }
+      }
+
+      let parserWithMissingLiteralValue = {
+        ...typescriptParser,
+        parseForESLint: wrapParser(typescriptParser.parseForESLint),
+        parse: wrapParser(typescriptParser.parse),
+      }
test/rules/sort-export-attributes.test.ts (2)

25-25: Fix test description: "import" should be "export"

Test descriptions incorrectly refer to "import attributes" instead of "export attributes".

-    it('sorts import attributes', async () => {
+    it('sorts export attributes', async () => {
-    it('sorts multiline import attributes', async () => {
+    it('sorts multiline export attributes', async () => {

Apply similar changes to lines 276, 301, 551, 576, and 831.

Also applies to: 276-276, 551-551


959-973: Consider extracting shared test utilities

The removeLiteralValue function and parser wrapping logic is duplicated from sort-import-attributes.test.ts. Consider extracting these into shared test utilities.

Would you like me to help create a shared test utility module for these common testing patterns?

rules/sort-export-attributes/types.ts (6)

17-20: Fix documentation comment - refers to wrong rule.

The JSDoc comment states "Configuration for a single custom group in import attributes sorting" but this file is for export attributes, not import attributes.

 /**
- * Configuration for a single custom group in import attributes sorting.
+ * Configuration for a single custom group in export attributes sorting.
  *
  * Allows defining custom groups based on attribute name patterns.
  */

47-51: Fix documentation comment - refers to wrong rule.

The JSDoc comment mentions "import attributes" but this should refer to "export attributes" since this is the export attributes rule.

     /**
-     * Custom groups for organizing import attributes. Allows defining groups
-     * based on attribute names and values.
+     * Custom groups for organizing export attributes. Allows defining groups
+     * based on attribute names and values.
      */

53-57: Fix documentation comment - refers to wrong rule.

The JSDoc comment mentions "import attributes" but should refer to "export attributes".

     /**
-     * Partition import attributes by comment delimiters. Attributes separated
-     * by specific comments are sorted independently.
+     * Partition export attributes by comment delimiters. Attributes separated
+     * by specific comments are sorted independently.
      */

59-63: Fix documentation comment - refers to wrong rule.

The JSDoc comment mentions "import attributes" but should refer to "export attributes".

     /**
-     * Controls the placement of newlines between different groups of import
-     * attributes.
+     * Controls the placement of newlines between different groups of export
+     * attributes.
      */

65-69: Fix documentation comment - refers to wrong rule.

The JSDoc comment mentions "import attributes" but should refer to "export attributes".

     /**
-     * Defines the order and grouping of import attributes. Attributes are
-     * sorted within their groups and groups are ordered as specified.
+     * Defines the order and grouping of export attributes. Attributes are
+     * sorted within their groups and groups are ordered as specified.
      */

71-75: Fix documentation comment - refers to wrong rule.

The JSDoc comment mentions "import attributes" but should refer to "export attributes".

     /**
-     * Whether to partition import attributes by newlines. When true, attributes
-     * separated by empty lines are sorted independently.
+     * Whether to partition export attributes by newlines. When true, attributes
+     * separated by empty lines are sorted independently.
      */
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 73dd08b and 4b0a823.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (24)
  • docs/content/rules/sort-export-attributes.mdx (1 hunks)
  • docs/content/rules/sort-import-attributes.mdx (1 hunks)
  • docs/content/rules/sort-interfaces.mdx (3 hunks)
  • docs/content/rules/sort-jsx-props.mdx (3 hunks)
  • docs/content/rules/sort-objects.mdx (4 hunks)
  • docs/public/llms.txt (1 hunks)
  • index.ts (3 hunks)
  • package.json (4 hunks)
  • readme.md (1 hunks)
  • rules/sort-export-attributes.ts (1 hunks)
  • rules/sort-export-attributes/types.ts (1 hunks)
  • rules/sort-import-attributes.ts (1 hunks)
  • rules/sort-import-attributes/types.ts (1 hunks)
  • rules/sort-interfaces.ts (2 hunks)
  • rules/sort-jsx-props.ts (6 hunks)
  • rules/sort-jsx-props/types.ts (4 hunks)
  • rules/sort-object-types.ts (9 hunks)
  • rules/sort-object-types/types.ts (3 hunks)
  • rules/sort-switch-case.ts (2 hunks)
  • test/rules/sort-export-attributes.test.ts (1 hunks)
  • test/rules/sort-import-attributes.test.ts (1 hunks)
  • test/rules/sort-interfaces.test.ts (16 hunks)
  • test/rules/sort-jsx-props.test.ts (35 hunks)
  • test/rules/sort-object-types.test.ts (19 hunks)
✅ Files skipped from review due to trivial changes (3)
  • docs/content/rules/sort-export-attributes.mdx
  • readme.md
  • docs/public/llms.txt
🚧 Files skipped from review as they are similar to previous changes (2)
  • rules/sort-switch-case.ts
  • rules/sort-jsx-props.ts
🧰 Additional context used
🧬 Code graph analysis (10)
test/rules/sort-export-attributes.test.ts (2)
utils/alphabet.ts (1)
  • Alphabet (46-467)
test/utils/validate-rule-json-schema.ts (1)
  • validateRuleJsonSchema (8-19)
rules/sort-import-attributes/types.ts (3)
types/common-options.ts (6)
  • RegexOption (477-477)
  • CustomGroupsOption (103-140)
  • PartitionByCommentOption (288-303)
  • NewlinesBetweenOption (203-226)
  • GroupsOptions (445-451)
  • CommonOptions (23-73)
utils/common-json-schemas.ts (1)
  • regexJsonSchema (219-228)
types/sorting-node.ts (1)
  • SortingNode (18-102)
test/rules/sort-import-attributes.test.ts (2)
utils/alphabet.ts (1)
  • Alphabet (46-467)
test/utils/validate-rule-json-schema.ts (1)
  • validateRuleJsonSchema (8-19)
rules/sort-export-attributes/types.ts (3)
types/common-options.ts (6)
  • RegexOption (477-477)
  • CustomGroupsOption (103-140)
  • PartitionByCommentOption (288-303)
  • NewlinesBetweenOption (203-226)
  • GroupsOptions (445-451)
  • CommonOptions (23-73)
utils/common-json-schemas.ts (1)
  • regexJsonSchema (219-228)
types/sorting-node.ts (1)
  • SortingNode (18-102)
rules/sort-import-attributes.ts (19)
rules/sort-import-attributes/types.ts (1)
  • Options (45-77)
utils/create-eslint-rule.ts (1)
  • createEslintRule (32-35)
utils/is-sortable.ts (1)
  • isSortable (7-9)
utils/get-settings.ts (1)
  • getSettings (91-136)
utils/complete.ts (1)
  • complete (30-36)
utils/validate-custom-sort-configuration.ts (1)
  • validateCustomSortConfiguration (25-35)
utils/validate-generated-groups-configuration.ts (1)
  • validateGeneratedGroupsConfiguration (74-95)
utils/validate-newlines-and-partition-configuration.ts (1)
  • validateNewlinesAndPartitionConfiguration (98-119)
utils/get-eslint-disabled-lines.ts (1)
  • getEslintDisabledLines (45-97)
utils/compute-group.ts (1)
  • computeGroup (75-113)
utils/does-custom-group-match.ts (1)
  • doesCustomGroupMatch (121-141)
utils/is-node-eslint-disabled.ts (1)
  • isNodeEslintDisabled (27-32)
utils/range-to-diff.ts (1)
  • rangeToDiff (32-41)
utils/should-partition.ts (1)
  • shouldPartition (69-95)
utils/sort-nodes-by-groups.ts (1)
  • sortNodesByGroups (106-162)
utils/get-custom-groups-compare-options.ts (1)
  • buildGetCustomGroupOverriddenOptionsFunction (137-148)
utils/report-all-errors.ts (1)
  • reportAllErrors (203-325)
utils/common-json-schemas.ts (6)
  • commonJsonSchemas (139-140)
  • buildCustomGroupsArrayJsonSchema (302-351)
  • partitionByCommentJsonSchema (241-262)
  • partitionByNewLineJsonSchema (268-272)
  • newlinesBetweenJsonSchema (146-158)
  • groupsJsonSchema (165-190)
utils/report-errors.ts (4)
  • MISSED_SPACING_ERROR (33-34)
  • EXTRA_SPACING_ERROR (30-31)
  • GROUP_ORDER_ERROR (27-28)
  • ORDER_ERROR (21-22)
rules/sort-export-attributes.ts (21)
rules/sort-imports.ts (1)
  • MessageId (59-65)
rules/sort-array-includes.ts (1)
  • defaultOptions (60-74)
rules/sort-export-attributes/types.ts (1)
  • Options (45-77)
utils/create-eslint-rule.ts (1)
  • createEslintRule (32-35)
utils/is-sortable.ts (1)
  • isSortable (7-9)
utils/get-settings.ts (1)
  • getSettings (91-136)
utils/complete.ts (1)
  • complete (30-36)
utils/validate-custom-sort-configuration.ts (1)
  • validateCustomSortConfiguration (25-35)
utils/validate-generated-groups-configuration.ts (1)
  • validateGeneratedGroupsConfiguration (74-95)
utils/validate-newlines-and-partition-configuration.ts (1)
  • validateNewlinesAndPartitionConfiguration (98-119)
utils/get-eslint-disabled-lines.ts (1)
  • getEslintDisabledLines (45-97)
utils/compute-group.ts (1)
  • computeGroup (75-113)
utils/does-custom-group-match.ts (1)
  • doesCustomGroupMatch (121-141)
utils/is-node-eslint-disabled.ts (1)
  • isNodeEslintDisabled (27-32)
utils/range-to-diff.ts (1)
  • rangeToDiff (32-41)
utils/should-partition.ts (1)
  • shouldPartition (69-95)
utils/sort-nodes-by-groups.ts (1)
  • sortNodesByGroups (106-162)
utils/get-custom-groups-compare-options.ts (1)
  • buildGetCustomGroupOverriddenOptionsFunction (137-148)
utils/report-all-errors.ts (1)
  • reportAllErrors (203-325)
utils/common-json-schemas.ts (6)
  • commonJsonSchemas (139-140)
  • buildCustomGroupsArrayJsonSchema (302-351)
  • partitionByCommentJsonSchema (241-262)
  • partitionByNewLineJsonSchema (268-272)
  • newlinesBetweenJsonSchema (146-158)
  • groupsJsonSchema (165-190)
utils/report-errors.ts (4)
  • MISSED_SPACING_ERROR (33-34)
  • EXTRA_SPACING_ERROR (30-31)
  • GROUP_ORDER_ERROR (27-28)
  • ORDER_ERROR (21-22)
rules/sort-object-types/types.ts (2)
types/common-options.ts (3)
  • RegexOption (477-477)
  • CustomGroupsOption (103-140)
  • FallbackSortOption (319-331)
types/join-with-dash.ts (1)
  • JoinWithDash (4-4)
rules/sort-jsx-props/types.ts (2)
types/common-options.ts (1)
  • CustomGroupsOption (103-140)
rules/sort-named-imports/types.ts (3)
  • SingleCustomGroup (74-92)
  • Selector (109-109)
  • allSelectors (156-156)
rules/sort-object-types.ts (3)
utils/filter-options-by-all-names-match.ts (1)
  • filterOptionsByAllNamesMatch (80-94)
utils/filter-options-by-declaration-comment-matches.ts (1)
  • filterOptionsByDeclarationCommentMatches (14-39)
utils/matches.ts (1)
  • matches (39-60)
rules/sort-interfaces.ts (2)
rules/sort-array-includes.ts (1)
  • defaultOptions (60-74)
rules/sort-jsx-props/types.ts (1)
  • Options (24-65)
🔇 Additional comments (30)
rules/sort-jsx-props/types.ts (1)

48-49: API shape LGTM

customGroups now uses the shared CustomGroupsOption. Consistent with other rules.

rules/sort-interfaces.ts (2)

20-35: Defaults updated to array-based API and added order/groups — looks good

Matches repo-wide changes (array customGroups, explicit order/groups).


48-50: Passing parentNode and context — correct

The call now forwards parent node and context explicitly; aligns with sort-object-types API.

docs/content/rules/sort-jsx-props.mdx (1)

269-287: Docs reflect array-based customGroups — good

Examples and usage now show customGroups: [] and per-group descriptors; consistent with v5 API.

Also applies to: 483-506, 522-535

docs/content/rules/sort-interfaces.mdx (2)

330-343: customGroups migration example looks good.

Array-based descriptors read clearly and match the new API surface.

Please confirm the JSON schema warns on the old object-map shape for this rule.


375-393: Nice addition: declarationCommentMatchesPattern.

Example is clear and aligns with “do not sort” use cases.

test/rules/sort-interfaces.test.ts (3)

2443-2497: Coverage for declarationCommentMatchesPattern looks solid.

Good positive/negative tests for the new matcher.


2321-2349: allNamesMatchPattern with multi-config precedence: good scenarios.

The RGB cases validate selector routing correctly.

Also applies to: 4953-4981, 7507-7535


552-584: Confirm availability of the 'member' predefined group for sort-interfaces.

Tests depend on 'member' being a valid group token. Ensure rule docs/types surface it consistently.

Also applies to: 586-618, 3184-3216, 3219-3250, 5745-5777, 5780-5811

rules/sort-object-types/types.ts (3)

35-40: Add declarationCommentMatchesPattern: LGTM.

Matches Options/useConfigurationIf across rules.


58-64: customGroups AdditionalOptions shape: LGTM.

Fallback sort extension per group is clear and typed.


228-238: PropertyGroup introduction: LGTM.

This aligns with removing the standalone multiline selector.

test/rules/sort-jsx-props.test.ts (2)

203-204: Group id rename to shorthand-prop/multiline-prop looks correct.

Updated group ids in both config and error data align with the new public API.

Also applies to: 224-226, 259-260, 284-286, 1538-1539, 1559-1561, 1594-1595, 1619-1623, 2866-2867, 2887-2891, 2922-2923, 2947-2951


329-335: Migration to array-based customGroups is consistent.

Use of elementNamePattern/elementValuePattern and anyOf mirrors the new schema; per‑group overrides exercised appropriately.

Also applies to: 867-872, 934-942, 971-997, 1079-1092, 1664-1671

rules/sort-object-types.ts (5)

98-102: Good: customGroups JSON schema now uses the array builder.

Matches the public API shift and keeps fallbackSort.sortBy supported.


93-96: New conditional: declarationCommentMatchesPattern.

Welcome addition; enables doc‑driven config switching.


67-77: defaultOptions updates align with new Options[number] shape.

Type and defaults (customGroups: []) look right.


382-426: Context option selection helper is clear and deterministic.

Filters by allNamesMatch and declaration comment, then checks declaration name. Good separation of concerns.


197-206: Approve: core sorting pipeline refactor — helpers verified

  • Skips call/construct signatures; uses predefined groups + custom matcher; partitions with shouldPartition and tracks partitionId; honors value-based sorting via isNodeIgnoredForGroup.
  • Sanity check: exports present at utils/get-lines-between.ts, utils/should-partition.ts, utils/sort-nodes-by-groups.ts. No further issues spotted.
rules/sort-export-attributes.ts (1)

204-212: LGTM! Helper function handles both key types effectively

The getAttributeName function correctly handles both Identifier and Literal key types, with a proper fallback to source text when the value is missing.

index.ts (1)

6-7: LGTM! New rules properly integrated

The new sort-import-attributes and sort-export-attributes rules are correctly imported and registered in the plugin configuration.

Also applies to: 31-32, 79-80

package.json (2)

14-14: LGTM! ESM migration properly configured

The conversion to ES modules with "type": "module" and the Node.js version requirement update (^20.0.0 || >=22.0.0) align well with the v5.0.0 breaking changes.

Also applies to: 129-129


60-61: Keep @typescript-eslint/types in dependencies — runtime exports are imported.

Value imports found that require the package at runtime: utils/is-partition-comment.ts:3 (AST_TOKEN_TYPES), rules/sort-object-types/is-member-optional.ts:3 (AST_NODE_TYPES). Many other files use import type only, but because runtime exports are used, do not move the package to devDependencies.

Likely an incorrect or invalid review comment.

test/rules/sort-import-attributes.test.ts (2)

959-973: Excellent edge case testing!

The test for handling missing literal values through AST manipulation is a clever way to ensure the rule handles edge cases gracefully.


1243-1244: LGTM! Comprehensive test coverage

The test suite is thorough and covers all major scenarios including:

  • Multiple sorting strategies
  • Grouping and partitioning
  • ESLint disable directives
  • Edge cases with missing values
  • Schema validation
test/rules/sort-export-attributes.test.ts (1)

950-955: LGTM! JSON schema validation included

Good practice including JSON schema validation in the test suite.

docs/content/rules/sort-import-attributes.mdx (1)

1-274: LGTM - Well-structured documentation for the new import attributes rule.

The documentation is comprehensive and properly aligned with the new sort-import-attributes rule. Based on the web search results, import attributes are a new ECMAScript 2025 feature that "allows module import statements and dynamic imports to pass on more information alongside the module specifier" with syntax like import json from "./foo.json" with { type: "json" }. This documentation correctly captures the feature's purpose and configuration options.

rules/sort-import-attributes/types.ts (1)

1-81: LGTM - Consistent type definitions following established patterns.

The type definitions properly follow the established patterns from other sorting rules in the codebase, with appropriate use of common options, custom groups, and JSON schema definitions. The interface structure aligns well with the type definitions used in rules/sort-export-attributes/types.ts.

rules/sort-import-attributes.ts (2)

203-212: LGTM - Proper attribute name extraction.

The helper function correctly handles both Identifier and literal keys for import attributes, with appropriate fallback to source text. This aligns with the AST structure for import attributes.


60-201: LGTM - Well-structured rule implementation following established patterns.

The rule implementation follows the established patterns from other sorting rules in the codebase, with proper:

  • Option validation and configuration
  • ESLint disabled lines handling
  • Partitioning logic
  • Group computation and sorting
  • JSON schema definition

The implementation properly integrates with the plugin's infrastructure and provides appropriate error messages for the four different scenarios.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (4)
docs/content/rules/sort-objects.mdx (4)

413-415: Type for groups is too narrow (example below uses an object).

Docs show { newlinesBetween: 0 } inside groups, but the declared type excludes it.

-  type: `Array<string | string[]>`
+  type: `Array<string | string[] | { newlinesBetween: number }>`

521-555: customGroups “type” still shows the deprecated object-map shape.

The section deprecates the map but the type line advertises it. Replace with the array form.

-<sub>
-  type: `{ [groupName: string]: string | string[] }`
-</sub>
-<sub>default: `[]`</sub>
+<sub>
+  type: `Array<CustomGroupDefinition | CustomGroupAnyOfDefinition>`
+</sub>
+<sub>default: `[]`</sub>

699-731: Legacy Config block may conflict with “ESM-only” and ESLint v9 focus.

If v5 drops ESLint v8, consider removing or clearly labeling this as pre-v5/v8-only to avoid confusion.

-    {
-      source: dedent`
-        // .eslintrc.js
-        module.exports = {
-          plugins: [
-            'perfectionist',
-          ],
-          rules: {
-            'perfectionist/sort-objects': [
-              'error',
-              {
-                ...
-              },
-            ],
-          },
-        }
-      `,
-      name: 'Legacy Config',
-      value: 'legacy',
-    },
+    // (Optional) Include legacy config only if supporting ESLint v8 in this version.

744-746: Fix broken Test source link in docs

rules/sort-objects.ts exists; the docs link points to test/sort-objects.test.ts (missing). The actual test is at test/rules/sort-objects.test.ts on main — update docs/content/rules/sort-objects.mdx (lines 744–746) to point to that path.

🧹 Nitpick comments (5)
docs/content/rules/sort-objects.mdx (3)

166-167: Minor wording nit: link text should say “groups”.

Change “[grouping]” to “[groups]” to match the option name.

- - 'unsorted' — Do not sort items. [`grouping`](#groups) and [`newlines behavior`](#newlinesbetween) are still enforced.
+ - 'unsorted' — Do not sort items. [`groups`](#groups) and [`newlines behavior`](#newlinesbetween) are still enforced.

248-251: Make RegExpPattern flags optional for consistency.

Elsewhere flags are optional; keep it aligned here.

- - `RegExpPattern = string | { pattern: string; flags: string}` — A regexp pattern to specify which comments should act as delimiters.
+ - `RegExpPattern = string | { pattern: string; flags?: string }` — A regexp pattern to specify which comments should act as delimiters.

323-327: Unify optionality of flags across patterns.

Use flags?: string for all unions to match other sections and typical typing.

-    allNamesMatchPattern?: string | string[] | { pattern: string; flags: string } | { pattern: string; flags: string }[]
-    callingFunctionNamePattern?: string | string[] | { pattern: string; flags: string } | { pattern: string; flags: string }[]
-    declarationCommentMatchesPattern?: string | string[] | { pattern: string; flags: string } | { pattern: string; flags: string }[]
+    allNamesMatchPattern?: string | string[] | { pattern: string; flags?: string } | { pattern: string; flags?: string }[]
+    callingFunctionNamePattern?: string | string[] | { pattern: string; flags?: string } | { pattern: string; flags?: string }[]
+    declarationCommentMatchesPattern?: string | string[] | { pattern: string; flags?: string } | { pattern: string; flags?: string }[]
rules/sort-objects/types.ts (2)

148-155: Selector union dropped ‘multiline’, but helper map/docs still reference it.

Selector no longer includes 'multiline', yet AllowedModifiersPerSelector and its JSDoc still define a 'multiline' selector entry. Clean up to avoid confusion.

Apply:

 interface AllowedModifiersPerSelector {
   /** Property members can be multiline, optional, or required. */
   property: MultilineModifier | OptionalModifier | RequiredModifier

   /** Generic members can be multiline, optional, or required. */
   member: MultilineModifier | OptionalModifier | RequiredModifier

   /** Method members can be multiline, optional, or required. */
   method: MultilineModifier | OptionalModifier | RequiredModifier

-  /** Multiline members can only be optional or required. */
-  multiline: OptionalModifier | RequiredModifier
-
-  /** Index signatures are not supported in regular objects. */
-  'index-signature': never
 }

Also adjust the nearby comments to reflect that “multiline” is only a modifier, not a selector.

Also applies to: 162-177


290-310: Make exported registries immutable to prevent accidental mutation.

Use const for arrays/registry objects.

-export let allSelectors: Selector[] = ['member', 'method', 'property']
+export const allSelectors: Selector[] = ['member', 'method', 'property']

-export let allModifiers: Modifier[] = ['optional', 'required', 'multiline']
+export const allModifiers: Modifier[] = ['optional', 'required', 'multiline']

-export let singleCustomGroupJsonSchema: Record<string, JSONSchema4> = {
+export const singleCustomGroupJsonSchema: Record<string, JSONSchema4> = {

If you want extra safety: type them as readonly arrays or Object.freeze(...).

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4b0a823 and 4256997.

📒 Files selected for processing (3)
  • docs/content/rules/sort-objects.mdx (4 hunks)
  • rules/sort-objects.ts (11 hunks)
  • rules/sort-objects/types.ts (5 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
rules/sort-objects/types.ts (1)
types/common-options.ts (2)
  • RegexOption (477-477)
  • CustomGroupsOption (103-140)
rules/sort-objects.ts (5)
rules/sort-objects/types.ts (1)
  • Options (25-114)
utils/common-json-schemas.ts (1)
  • regexJsonSchema (219-228)
utils/filter-options-by-all-names-match.ts (1)
  • filterOptionsByAllNamesMatch (80-94)
utils/filter-options-by-declaration-comment-matches.ts (1)
  • filterOptionsByDeclarationCommentMatches (14-39)
rules/sort-objects/get-first-node-parent-with-type.ts (1)
  • getFirstNodeParentWithType (21-46)
🔇 Additional comments (18)
docs/content/rules/sort-objects.mdx (2)

510-519: Cross-check: object in groups relies on the broader type.

This example requires the widened groups type proposed above.


638-655: Good illustrative example of array-based customGroups.

Clear migration-friendly example; regexes and grouping look correct.

rules/sort-objects.ts (12)

27-27: Import for declaration-comment filter: LGTM.

This aligns with new useConfigurationIf.declarationCommentMatchesPattern support.


37-37: Import for all-names-match filter: LGTM.

Matches the new options flow.


98-103: Switch to computeMatchedContextOptions: LGTM.

Good consolidation of context resolution.


117-119: Object declarations gate: LGTM.

Early‑return is correct for non‑declaration contexts when disabled.


355-377: Helper to exclude ESLint‑disabled nodes: LGTM.

Clear separation before dependency sorting; no behavior regressions spotted.


439-441: Top‑level customGroups schema: LGTM.

Correct move to array schema via builder.


566-571: Normalize callee text to reduce false positives in callingFunctionNamePattern.

Use a stable name (Identifier or MemberExpression.property) before falling back to raw source.
[Suggest_recommended_refactor]

See diff in the previous comment adding getCalleeName and swapping sourceCode.getText(...) for it.


575-613: Variable/Property ancestor resolution: LGTM.

Clean separation and safe name extraction for Identifier keys.


497-503: Fix parent node chosen for declarationCommentMatchesPattern.

When the nearest ancestor is a Property, you currently treat it as VariableDeclarator and hop to .parent (ObjectExpression), which skews comment matching. Use the actual ancestor kind.

Apply:

-  let parentNodeForDeclarationComment = null
-  if (objectParent) {
-    parentNodeForDeclarationComment =
-      objectParent.type === 'VariableDeclarator'
-        ? objectParent.node.parent
-        : objectParent.node
-  }
+  let parentNodeForDeclarationComment =
+    objectParent == null
+      ? null
+      : objectParent.type === 'VariableDeclarator'
+        ? objectParent.node.parent
+        : objectParent.node

532-573: Preserve actual ancestor kind in getObjectParent (don’t label Property as VariableDeclarator).

The current union and return path conflate Property with VariableDeclarator, causing downstream mis‑classification.

Apply:

-function getObjectParent({
+function getObjectParent({
   onlyFirstParent,
-  sourceCode,
+  sourceCode,
   node,
 }: {
   node: TSESTree.ObjectExpression | TSESTree.ObjectPattern
-  sourceCode: TSESLint.SourceCode
+  sourceCode: TSESLint.SourceCode
   onlyFirstParent: boolean
-}):
-  | {
-      node: TSESTree.VariableDeclarator | TSESTree.Property
-      type: 'VariableDeclarator'
-      name: string | null
-    }
-  | {
-      node: TSESTree.CallExpression
-      type: 'CallExpression'
-      name: string | null
-    }
-  | null {
+}):
+  | { node: TSESTree.VariableDeclarator; type: 'VariableDeclarator'; name: string | null }
+  | { node: TSESTree.Property; type: 'Property'; name: string | null }
+  | { node: TSESTree.CallExpression; type: 'CallExpression'; name: string | null }
+  | null {
   let variableParent = getVariableParent({ onlyFirstParent, node })
   if (variableParent) {
-    return {
-      type: 'VariableDeclarator',
-      name: variableParent.name,
-      node: variableParent.node,
-    }
+    return variableParent.node.type === TSESTree.AST_NODE_TYPES.VariableDeclarator
+      ? {
+          type: 'VariableDeclarator',
+          name: variableParent.name,
+          node: variableParent.node,
+        }
+      : {
+          type: 'Property',
+          name: variableParent.name,
+          node: variableParent.node,
+        }
   }
   let callParent = getFirstNodeParentWithType({
     allowedTypes: [TSESTree.AST_NODE_TYPES.CallExpression],
     onlyFirstParent,
     node,
   })
   if (callParent) {
     return {
-      name: sourceCode.getText(callParent.callee),
+      name: getCalleeName(callParent.callee) ?? sourceCode.getText(callParent.callee),
       type: 'CallExpression',
       node: callParent,
     }
   }
   return null
 }
+
+function getCalleeName(expr: TSESTree.Expression): string | null {
+  if (expr.type === 'Identifier') return expr.name
+  if (
+    expr.type === 'MemberExpression' &&
+    !expr.computed &&
+    expr.property.type === 'Identifier'
+  ) {
+    return expr.property.name
+  }
+  return null
+}

66-84: Default options are consistent with documentation — no action required.

customGroups: [], objectDeclarations: true, and the other defaults in rules/sort-objects.ts are reflected in docs/examples (docs/content/rules/sort-objects.mdx) and tests.


425-431: No change required — buildUseConfigurationIfJsonSchema already includes allNamesMatchPattern.
buildUseConfigurationIfJsonSchema (utils/common-json-schemas.ts) defines allNamesMatchPattern: regexJsonSchema in its properties, so the additionalProperties in rules/sort-objects.ts do not need to repeat it.

Likely an incorrect or invalid review comment.

rules/sort-objects/types.ts (4)

32-37: Verify new conditional option is wired end‑to‑end

declarationCommentMatchesPattern (rules/sort-objects/types.ts) was added — confirm:

  • it's declared in the rule's meta.schema,
  • it's parsed/merged during option resolution (option normalizer / useConfigurationIf),
  • tests exist for positive and negative cases.

Run to help locate usages:
rg -n "declarationCommentMatchesPattern|useConfigurationIf" -C3 --hidden -g '!/dist/'


56-56: Move to array-based customGroups acknowledged.

Type switch to CustomGroupsOption<SingleCustomGroup> aligns with the new shared option model. Verify older shapes aren’t still accepted anywhere (to avoid silent config drift).


238-238: Group union updated — double‑check for lingering multiline group strings.

With MultilineGroup removed, audit tests/docs for tokens like multiline-property etc., and ensure schema for groups can’t accept them.


100-104: Confirm intent: remove legacy ignorePattern or keep and document

Docs and commits mark ignorePattern as deprecated/dropped, yet it still appears in code and tests (rules/sort-objects/types.ts — ~line 104; rules/sort-objects.ts — schema/uses at ~lines 77/128/445; utils/get-settings.ts; test/rules/sort-objects.test.ts; docs/content/rules/sort-object-types.mdx).

Action — pick one:

  • Remove: delete ignorePattern from types, implementation, JSON schema and tests; add a migration note in docs/changelog.
  • Keep: remove the DEPRECATED marker from docs and add an explicit migration/compatibility note explaining why it remains.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (2)
index.ts (2)

75-98: Make rules map immutable and type-checked.

Use const and satisfies for safer types and to prevent accidental reassignment.

Apply:

-export let rules = {
+export const rules = {
   'sort-variable-declarations': sortVariableDeclarations,
   'sort-intersection-types': sortIntersectionTypes,
   'sort-import-attributes': sortImportAttributes,
   'sort-export-attributes': sortExportAttributes,
   'sort-heritage-clauses': sortHeritageClauses,
   'sort-array-includes': sortArrayIncludes,
   'sort-named-imports': sortNamedImports,
   'sort-named-exports': sortNamedExports,
   'sort-object-types': sortObjectTypes,
   'sort-union-types': sortUnionTypes,
   'sort-switch-case': sortSwitchCase,
   'sort-decorators': sortDecorators,
   'sort-interfaces': sortInterfaces,
   'sort-jsx-props': sortJsxProps,
   'sort-modules': sortModules,
   'sort-classes': sortClasses,
   'sort-imports': sortImports,
   'sort-exports': sortExports,
   'sort-objects': sortObjects,
   'sort-enums': sortEnums,
   'sort-sets': sortSets,
   'sort-maps': sortMaps,
-}
+} satisfies Record<string, Rule.RuleModule>

Optional: freeze to guard against mutation at runtime:

Object.freeze(rules)

105-105: Prefer “satisfies” over double type assertion for plugin; simplify getRules usage.

Avoid as unknown as and take advantage of satisfies. Also, reference the local rules map to remove the non-null assertion.

Outside this hunk, consider:

const plugin = {
  meta: { version: packageVersion, name: packageName },
  rules,
} satisfies ESLint.Plugin

// And in getRules:
function getRules(options: BaseOptions): Linter.RulesRecord {
  return Object.fromEntries(
    Object.keys(rules).map(ruleName => [
      `${pluginName}/${ruleName}`,
      ['error', options],
    ]),
  )
}
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4256997 and 4aa823b.

📒 Files selected for processing (1)
  • index.ts (4 hunks)
🔇 Additional comments (3)
index.ts (3)

31-32: PluginConfig interface updated with new rules — LGTM.


170-170: Default export exposing configs — LGTM.


6-7: New rule modules verified — default exports, tests, and docs are in place.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (9)
package.json (1)

3-3: Bump the package version for the v5.0.0 release.

This release PR still publishes version 4.15.0. The release automation (changelogen tag, git tag, changelog text) and consumers will all misidentify the release unless package.json is set to 5.0.0.

docs/content/rules/sort-array-includes.mdx (1)

491-492: Update Test source link to include rules/
Replace the test link so it points to test/rules/sort-array-includes.test.ts:

- [Test source](https://github.com/azat-io/eslint-plugin-perfectionist/blob/main/test/sort-array-includes.test.ts)
+ [Test source](https://github.com/azat-io/eslint-plugin-perfectionist/blob/main/test/rules/sort-array-includes.test.ts)
docs/content/rules/sort-imports.mdx (1)

724-726: Fix outdated “Test source” link path.

Tests were migrated under test/rules; update the link.

Apply:

-- [Test source](https://github.com/azat-io/eslint-plugin-perfectionist/blob/main/test/sort-imports.test.ts)
+- [Test source](https://github.com/azat-io/eslint-plugin-perfectionist/blob/main/test/rules/sort-imports.test.ts)
test/rules/sort-jsx-props.test.ts (1)

13-22: Set parser on languageOptions, not inside parserOptions.

ESLint v9-style config expects languageOptions.parser. Current placement can fall back to Espree.

Apply:

-    languageOptions: {
-      parserOptions: {
+    languageOptions: {
+      parser: typescriptParser,
+      parserOptions: {
         tsconfigRootDir: path.join(import.meta.dirname, '../fixtures'),
         extraFileExtensions: ['.svelte', '.astro', '.vue'],
         ecmaFeatures: {
           jsx: true,
         },
         project: './tsconfig.json',
-        parser: typescriptParser,
       },
     },
rules/sort-imports.ts (1)

356-371: Enable spacing diagnostics for imports.

Pass a newlinesBetweenValueGetter to reportAllErrors so missed/extra blank lines are detected.

Apply:

   reportAllErrors<MessageId>({
@@
-    sourceCode,
-    options,
+    sourceCode,
+    options,
     context,
     nodes,
+    newlinesBetweenValueGetter: (left, right) =>
+      getLinesBetween(sourceCode, left, right),
   })

Add import:

@@
 import { complete } from '../utils/complete'
+import { getLinesBetween } from '../utils/get-lines-between'
docs/content/rules/sort-interfaces.mdx (2)

365-366: *Invalid regex example (‘Metadata$’)

Leading “*” is not a valid JS regex. Use a proper pattern.

Apply:

-        declarationMatchesPattern: '*Metadata$',
+        declarationMatchesPattern: '.*Metadata$',

753-755: Fix test source link path
Update the Test source URL to reflect its new location under test/rules:

- [Test source](https://github.com/azat-io/eslint-plugin-perfectionist/blob/main/test/sort-interfaces.test.ts)
+ [Test source](https://github.com/azat-io/eslint-plugin-perfectionist/blob/main/test/rules/sort-interfaces.test.ts)
docs/content/rules/sort-object-types.mdx (2)

341-343: *Invalid regex example (‘Metadata$’)

Use a valid pattern.

Apply:

-        declarationMatchesPattern: '*Metadata$',
+        declarationMatchesPattern: '.*Metadata$',

731-733: Fix “Test source” link path
Update link to include rules/ directory:

- [Test source](https://github.com/azat-io/eslint-plugin-perfectionist/blob/main/test/sort-object-types.test.ts)
+ [Test source](https://github.com/azat-io/eslint-plugin-perfectionist/blob/main/test/rules/sort-object-types.test.ts)
🧹 Nitpick comments (19)
docs/content/rules/sort-array-includes.mdx (2)

248-258: Include 'always' and 'never' in newlinesBetween docs

The shared NewlinesBetweenOption supports 'always' and 'never'. Reflect that here for consistency.

Apply:

-<sub>type: `number | 'ignore'`</sub>
+<sub>type: `number | 'ignore' | 'always' | 'never'`</sub>
@@
-- `'ignore'` — Do not report errors related to newlines.
-- `0` — No newlines are allowed.
-- Any other number — Enforce this number of newlines between each group, and forbid newlines inside groups.
+- `'ignore'` — Do not report errors related to newlines.
+- `'always'` — Require exactly one blank line between groups.
+- `'never'` — Disallow blank lines between groups.
+- `number` — Require exactly this number of blank lines between groups, and forbid newlines inside groups.

As per common options.


4-4: Fix typo: “includes” method

Use the correct method name in the short description.

-shortDescription: Enforce sorted arrays before include method
+shortDescription: Enforce sorted arrays before includes method
rules/sort-export-attributes.ts (1)

203-212: Deduplicate attribute name helper.

getAttributeName likely duplicates logic with sort-import-attributes. Consider extracting to utils to keep behavior consistent.

rules/sort-object-types/types.ts (1)

161-176: Remove unused “multiline” selector mapping.

AllowedModifiersPerSelector includes a “multiline” selector key, but Selector doesn’t include 'multiline'. This mapping is unreachable and may confuse readers. Recommend removing that key.

rules/sort-named-exports/types.ts (1)

94-95: Update JSDoc to reflect alias (no longer “Extended”)

The node type is now a direct alias; the “Extended” wording is misleading.

-/** Extended sorting node for named export specifiers. */
+/** Sorting node for named export specifiers. */
 export type SortNamedExportsSortingNode = SortingNode<TSESTree.ExportSpecifier>
test/rules/sort-export-attributes.test.ts (2)

821-829: Avoid heavy alphabet generation in tests

Alphabet.generateRecommendedAlphabet().sortByLocaleCompare('en-US') builds and sorts ~131k code points; it can slow the suite. Cache once per file (const) or move to a shared test util computed once per run.

-    let alphabet = Alphabet.generateRecommendedAlphabet()
+    const alphabet = Alphabet.generateRecommendedAlphabet()
       .sortByLocaleCompare('en-US')
       .getCharacters()

958-973: Stronger AST guard when mutating attributes

Be explicit about ExportNamedDeclaration to avoid accidental matches and tighten the type guard.

-      function removeLiteralValue(program: TSESTree.Program): void {
-        for (let statement of program.body) {
-          if (!('attributes' in statement)) {
-            continue
-          }
+      function removeLiteralValue(program: TSESTree.Program): void {
+        for (let statement of program.body) {
+          if (statement.type !== 'ExportNamedDeclaration' || !statement.attributes) {
+            continue
+          }
test/rules/sort-named-exports.test.ts (1)

4127-4136: Avoid heavy alphabet generation per run

Same perf note as other files: compute once (const) or share via a test util to reduce repeated ~131k sort cost.

-    let alphabet = Alphabet.generateRecommendedAlphabet()
+    const alphabet = Alphabet.generateRecommendedAlphabet()
       .sortByLocaleCompare('en-US')
       .getCharacters()
test/rules/sort-import-attributes.test.ts (1)

821-829: Avoid heavy alphabet generation in tests

Cache or share the computed alphabet to speed up the suite; also prefer const.

-    let alphabet = Alphabet.generateRecommendedAlphabet()
+    const alphabet = Alphabet.generateRecommendedAlphabet()
       .sortByLocaleCompare('en-US')
       .getCharacters()
index.ts (3)

75-99: Make rules immutable and type-checked

Prefer const + satisfies for safer public API and better DX.

-export let rules = {
+export const rules = {
   'sort-variable-declarations': sortVariableDeclarations,
   'sort-intersection-types': sortIntersectionTypes,
   'sort-import-attributes': sortImportAttributes,
   'sort-export-attributes': sortExportAttributes,
   'sort-heritage-clauses': sortHeritageClauses,
   'sort-array-includes': sortArrayIncludes,
   'sort-named-imports': sortNamedImports,
   'sort-named-exports': sortNamedExports,
   'sort-object-types': sortObjectTypes,
   'sort-union-types': sortUnionTypes,
   'sort-switch-case': sortSwitchCase,
   'sort-decorators': sortDecorators,
   'sort-interfaces': sortInterfaces,
   'sort-jsx-props': sortJsxProps,
   'sort-modules': sortModules,
   'sort-classes': sortClasses,
   'sort-imports': sortImports,
   'sort-exports': sortExports,
   'sort-objects': sortObjects,
   'sort-enums': sortEnums,
   'sort-sets': sortSets,
   'sort-maps': sortMaps,
-}
+} satisfies PluginConfig['rules']

100-106: Type plugin directly; avoid double assertion

Use const and explicit type instead of “as unknown as”.

-let plugin = {
+const plugin: ESLint.Plugin = {
   meta: {
     version: packageVersion,
     name: packageName,
   },
-  rules,
-} as unknown as ESLint.Plugin
+  rules,
+}

108-115: Remove non-null assertion by using rules map directly

No need to go through plugin.rules!.

 function getRules(options: BaseOptions): Linter.RulesRecord {
   return Object.fromEntries(
-    Object.keys(plugin.rules!).map(ruleName => [
+    Object.keys(rules).map(ruleName => [
       `${pluginName}/${ruleName}`,
       ['error', options],
     ]),
   )
 }
rules/sort-import-attributes.ts (1)

45-58: Type consistency nit: prefer Options[number] over Options[0].

Matches usage elsewhere (e.g., other rules) and is semantically clearer.

Apply:

-let defaultOptions: Required<Options[0]> = {
+let defaultOptions: Required<Options[number]> = {
test/rules/sort-imports.test.ts (2)

1462-1475: Reduce repeated inline customGroups definitions in tests.

The same patterns for a/b/c and larger suites are duplicated across many cases. Extracting tiny helpers will cut noise and ease future API shifts.

Example helper (place near top of file):

function cg(...defs: Array<{ name: string; pattern: string | string[] | {pattern:string;flags?:string} }>) {
  return defs.map(d => ({ groupName: d.name, elementNamePattern: d.pattern }));
}

Then, in tests:

- customGroups: [
-   { groupName: 'a', elementNamePattern: 'a' },
-   { groupName: 'b', elementNamePattern: 'b' },
- ]
+ customGroups: cg({ name: 'a', pattern: 'a' }, { name: 'b', pattern: 'b' })

Also applies to: 1534-1551, 1613-1660, 5105-5118, 5176-5194, 5256-5269, 5290-5303, 7908-7917, 8762-8775, 8834-8851, 8914-8926, 8948-8960, 11094-11100, 11263-11308


2395-2395: Restore spies after tsconfig-based mocks to avoid cross-test leakage.

Several cases mock readClosestTsConfigByPath; ensure they’re restored, not just reset, to prevent overlapping spies in later tests.

Recommended:

  • Prefer vi.restoreAllMocks() in after/afterEach when using vi.spyOn in before/beforeEach.
  • Alternatively, add a suite-level afterEach(() => vi.restoreAllMocks()).

Example:

afterEach(() => {
  vi.restoreAllMocks()
})

If you want, I can sweep the file and open a patch to add restore hooks to the few cases that set up tsconfig mocks without a corresponding teardown.

Also applies to: 6057-6057, 9742-9742, 11618-11618, 11642-11642, 11666-11666, 11696-11696

docs/content/rules/sort-interfaces.mdx (1)

289-297: Fix newlinesBetween type and bullets to match runtime API

Tests and types accept 'always' | 'never' in addition to number | 'ignore'. Please update the docs to prevent confusion.

Apply:

-<sub>type: `number | 'ignore'`</sub>
+<sub>type: `number | 'ignore' | 'always' | 'never'`</sub>

-Specifies how to handle newlines between groups.
+Specifies how to handle newlines between groups.

-- `'ignore'` — Do not report errors related to newlines.
-- `0` — No newlines are allowed.
-- Any other number — Enforce this number of newlines between each group, and forbid newlines inside groups.
+- `'ignore'` — Do not report errors related to newlines.
+- `'always'` — Always require at least one blank line between groups.
+- `'never'` — Disallow blank lines between groups.
+- `0` — No newlines are allowed.
+- Any other number — Enforce this exact number of blank lines between groups, and forbid newlines inside groups.

As per common-options NewlinesBetweenOption. Based on learnings

docs/content/rules/sort-object-types.mdx (2)

264-272: Fix newlinesBetween type and bullets to match runtime/tested API

Docs should list 'always' and 'never' as accepted values.

Apply:

-<sub>type: `number | 'ignore'`</sub>
+<sub>type: `number | 'ignore' | 'always' | 'never'`</sub>

-Specifies how to handle newlines between groups.
+Specifies how to handle newlines between groups.

-- `'ignore'` — Do not report errors related to newlines.
-- `0` — No newlines are allowed.
-- Any other number — Enforce this number of newlines between each group, and forbid newlines inside groups.
+- `'ignore'` — Do not report errors related to newlines.
+- `'always'` — Always require at least one blank line between groups.
+- `'never'` — Disallow blank lines between groups.
+- `0` — No newlines are allowed.
+- Any other number — Enforce this exact number of blank lines between groups, and forbid newlines inside groups.

As per common-options NewlinesBetweenOption. Based on learnings


671-678: Remove deprecated ignorePattern from usage examples

The default config blocks still show ignorePattern, which is deprecated and removed elsewhere. Please drop it to avoid copy-paste confusion.

Apply:

-                  ignorePattern: [],

in both Flat and Legacy config snippets.

Also applies to: 704-711

rules/sort-decorators/types.ts (1)

39-41: Consider freezing the JSON schema object

Minor: mark schema as readonly to avoid accidental mutation.

Apply:

-export let singleCustomGroupJsonSchema: Record<string, JSONSchema4> = {
-  elementNamePattern: regexJsonSchema,
-}
+export const singleCustomGroupJsonSchema: Readonly<Record<string, JSONSchema4>> = {
+  elementNamePattern: regexJsonSchema,
+}
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ee4fe80 and 42ceb3c.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (67)
  • docs/content/rules/sort-array-includes.mdx (3 hunks)
  • docs/content/rules/sort-decorators.mdx (5 hunks)
  • docs/content/rules/sort-export-attributes.mdx (1 hunks)
  • docs/content/rules/sort-exports.mdx (0 hunks)
  • docs/content/rules/sort-heritage-clauses.mdx (5 hunks)
  • docs/content/rules/sort-import-attributes.mdx (1 hunks)
  • docs/content/rules/sort-imports.mdx (1 hunks)
  • docs/content/rules/sort-interfaces.mdx (3 hunks)
  • docs/content/rules/sort-intersection-types.mdx (1 hunks)
  • docs/content/rules/sort-jsx-props.mdx (3 hunks)
  • docs/content/rules/sort-named-exports.mdx (0 hunks)
  • docs/content/rules/sort-named-imports.mdx (0 hunks)
  • docs/content/rules/sort-object-types.mdx (3 hunks)
  • docs/content/rules/sort-objects.mdx (4 hunks)
  • docs/content/rules/sort-sets.mdx (3 hunks)
  • docs/public/llms.txt (1 hunks)
  • index.ts (4 hunks)
  • package.json (4 hunks)
  • readme.md (1 hunks)
  • rules/sort-array-includes.ts (5 hunks)
  • rules/sort-array-includes/types.ts (0 hunks)
  • rules/sort-classes.ts (1 hunks)
  • rules/sort-decorators.ts (6 hunks)
  • rules/sort-decorators/types.ts (1 hunks)
  • rules/sort-enums.ts (5 hunks)
  • rules/sort-export-attributes.ts (1 hunks)
  • rules/sort-export-attributes/types.ts (1 hunks)
  • rules/sort-exports.ts (2 hunks)
  • rules/sort-exports/types.ts (0 hunks)
  • rules/sort-heritage-clauses.ts (6 hunks)
  • rules/sort-heritage-clauses/types.ts (1 hunks)
  • rules/sort-import-attributes.ts (1 hunks)
  • rules/sort-import-attributes/types.ts (1 hunks)
  • rules/sort-imports.ts (6 hunks)
  • rules/sort-imports/types.ts (1 hunks)
  • rules/sort-interfaces.ts (2 hunks)
  • rules/sort-intersection-types.ts (1 hunks)
  • rules/sort-jsx-props.ts (6 hunks)
  • rules/sort-jsx-props/types.ts (4 hunks)
  • rules/sort-maps.ts (3 hunks)
  • rules/sort-modules.ts (2 hunks)
  • rules/sort-named-exports.ts (2 hunks)
  • rules/sort-named-exports/types.ts (1 hunks)
  • rules/sort-named-imports.ts (2 hunks)
  • rules/sort-named-imports/types.ts (1 hunks)
  • rules/sort-object-types.ts (9 hunks)
  • rules/sort-object-types/get-custom-groups-compare-options.ts (3 hunks)
  • rules/sort-object-types/types.ts (3 hunks)
  • rules/sort-objects.ts (11 hunks)
  • rules/sort-objects/types.ts (5 hunks)
  • rules/sort-switch-case.ts (2 hunks)
  • rules/sort-union-types.ts (1 hunks)
  • rules/sort-variable-declarations.ts (1 hunks)
  • test/rules/sort-array-includes.test.ts (12 hunks)
  • test/rules/sort-decorators.test.ts (2 hunks)
  • test/rules/sort-enums.test.ts (6 hunks)
  • test/rules/sort-export-attributes.test.ts (1 hunks)
  • test/rules/sort-exports.test.ts (0 hunks)
  • test/rules/sort-heritage-clauses.test.ts (5 hunks)
  • test/rules/sort-import-attributes.test.ts (1 hunks)
  • test/rules/sort-imports.test.ts (25 hunks)
  • test/rules/sort-interfaces.test.ts (16 hunks)
  • test/rules/sort-jsx-props.test.ts (35 hunks)
  • test/rules/sort-named-exports.test.ts (6 hunks)
  • test/rules/sort-named-imports.test.ts (6 hunks)
  • test/rules/sort-object-types.test.ts (19 hunks)
  • test/rules/sort-object-types/get-custom-groups-compare-options.test.ts (1 hunks)
💤 Files with no reviewable changes (6)
  • rules/sort-array-includes/types.ts
  • docs/content/rules/sort-exports.mdx
  • docs/content/rules/sort-named-exports.mdx
  • docs/content/rules/sort-named-imports.mdx
  • rules/sort-exports/types.ts
  • test/rules/sort-exports.test.ts
✅ Files skipped from review due to trivial changes (1)
  • docs/content/rules/sort-import-attributes.mdx
🚧 Files skipped from review as they are similar to previous changes (20)
  • test/rules/sort-enums.test.ts
  • docs/public/llms.txt
  • rules/sort-union-types.ts
  • rules/sort-modules.ts
  • docs/content/rules/sort-sets.mdx
  • rules/sort-interfaces.ts
  • rules/sort-variable-declarations.ts
  • rules/sort-switch-case.ts
  • rules/sort-export-attributes/types.ts
  • rules/sort-maps.ts
  • docs/content/rules/sort-export-attributes.mdx
  • rules/sort-classes.ts
  • docs/content/rules/sort-intersection-types.mdx
  • docs/content/rules/sort-jsx-props.mdx
  • readme.md
  • rules/sort-imports/types.ts
  • rules/sort-import-attributes/types.ts
  • test/rules/sort-named-imports.test.ts
  • rules/sort-enums.ts
  • docs/content/rules/sort-objects.mdx
🧰 Additional context used
🧬 Code graph analysis (25)
test/rules/sort-object-types/get-custom-groups-compare-options.test.ts (1)
rules/sort-object-types/types.ts (1)
  • Options (28-106)
rules/sort-decorators/types.ts (3)
types/common-options.ts (6)
  • CustomGroupsOption (103-140)
  • PartitionByCommentOption (288-303)
  • NewlinesBetweenOption (203-226)
  • GroupsOptions (445-451)
  • CommonOptions (23-73)
  • RegexOption (477-477)
types/sorting-node.ts (1)
  • SortingNode (18-102)
utils/common-json-schemas.ts (1)
  • regexJsonSchema (219-228)
rules/sort-array-includes.ts (6)
types/sorting-node.ts (1)
  • SortingNode (18-102)
rules/sort-array-includes/types.ts (2)
  • Options (24-68)
  • Selector (100-100)
utils/filter-options-by-all-names-match.ts (1)
  • filterOptionsByAllNamesMatch (80-94)
utils/sort-nodes-by-groups.ts (1)
  • sortNodesByGroups (106-162)
utils/get-custom-groups-compare-options.ts (1)
  • buildGetCustomGroupOverriddenOptionsFunction (137-148)
utils/report-all-errors.ts (1)
  • reportAllErrors (203-325)
rules/sort-exports.ts (6)
types/sorting-node.ts (1)
  • SortingNode (18-102)
rules/sort-array-includes.ts (1)
  • defaultOptions (60-74)
rules/sort-exports/types.ts (1)
  • Options (25-57)
utils/sort-nodes-by-groups.ts (1)
  • sortNodesByGroups (106-162)
utils/get-custom-groups-compare-options.ts (1)
  • buildGetCustomGroupOverriddenOptionsFunction (137-148)
utils/report-all-errors.ts (1)
  • reportAllErrors (203-325)
rules/sort-named-exports/types.ts (1)
types/sorting-node.ts (1)
  • SortingNode (18-102)
rules/sort-named-imports.ts (4)
rules/sort-named-imports/types.ts (1)
  • Options (26-66)
utils/sort-nodes-by-groups.ts (1)
  • sortNodesByGroups (106-162)
utils/get-custom-groups-compare-options.ts (1)
  • buildGetCustomGroupOverriddenOptionsFunction (137-148)
utils/report-all-errors.ts (1)
  • reportAllErrors (203-325)
rules/sort-object-types.ts (4)
rules/sort-object-types/types.ts (1)
  • Options (28-106)
utils/filter-options-by-all-names-match.ts (1)
  • filterOptionsByAllNamesMatch (80-94)
utils/filter-options-by-declaration-comment-matches.ts (1)
  • filterOptionsByDeclarationCommentMatches (14-39)
utils/matches.ts (1)
  • matches (39-60)
rules/sort-object-types/types.ts (2)
types/common-options.ts (3)
  • RegexOption (477-477)
  • CustomGroupsOption (103-140)
  • FallbackSortOption (319-331)
types/join-with-dash.ts (1)
  • JoinWithDash (4-4)
rules/sort-objects/types.ts (1)
types/common-options.ts (2)
  • RegexOption (477-477)
  • CustomGroupsOption (103-140)
rules/sort-named-exports.ts (5)
rules/sort-array-includes.ts (1)
  • defaultOptions (60-74)
rules/sort-named-exports/types.ts (1)
  • Options (26-66)
utils/sort-nodes-by-groups.ts (1)
  • sortNodesByGroups (106-162)
utils/get-custom-groups-compare-options.ts (1)
  • buildGetCustomGroupOverriddenOptionsFunction (137-148)
utils/report-all-errors.ts (1)
  • reportAllErrors (203-325)
rules/sort-heritage-clauses.ts (11)
rules/sort-heritage-clauses/types.ts (1)
  • Options (14-22)
utils/common-json-schemas.ts (4)
  • buildCustomGroupsArrayJsonSchema (302-351)
  • partitionByNewLineJsonSchema (268-272)
  • partitionByCommentJsonSchema (241-262)
  • newlinesBetweenJsonSchema (146-158)
utils/report-errors.ts (4)
  • MISSED_SPACING_ERROR (33-34)
  • EXTRA_SPACING_ERROR (30-31)
  • GROUP_ORDER_ERROR (27-28)
  • ORDER_ERROR (21-22)
utils/validate-newlines-and-partition-configuration.ts (1)
  • validateNewlinesAndPartitionConfiguration (98-119)
types/sorting-node.ts (1)
  • SortingNode (18-102)
utils/compute-group.ts (1)
  • computeGroup (75-113)
utils/does-custom-group-match.ts (1)
  • doesCustomGroupMatch (121-141)
utils/should-partition.ts (1)
  • shouldPartition (69-95)
utils/sort-nodes-by-groups.ts (1)
  • sortNodesByGroups (106-162)
utils/get-custom-groups-compare-options.ts (1)
  • buildGetCustomGroupOverriddenOptionsFunction (137-148)
utils/report-all-errors.ts (1)
  • reportAllErrors (203-325)
rules/sort-jsx-props.ts (5)
rules/sort-array-includes.ts (1)
  • defaultOptions (60-74)
rules/sort-jsx-props/types.ts (1)
  • Options (24-65)
utils/common-json-schemas.ts (1)
  • buildCustomGroupsArrayJsonSchema (302-351)
utils/filter-options-by-all-names-match.ts (1)
  • filterOptionsByAllNamesMatch (80-94)
utils/matches.ts (1)
  • matches (39-60)
rules/sort-object-types/get-custom-groups-compare-options.ts (1)
rules/sort-object-types/types.ts (1)
  • Options (28-106)
rules/sort-decorators.ts (6)
rules/sort-decorators/types.ts (1)
  • Options (16-29)
utils/common-json-schemas.ts (4)
  • buildCustomGroupsArrayJsonSchema (302-351)
  • partitionByNewLineJsonSchema (268-272)
  • newlinesBetweenJsonSchema (146-158)
  • groupsJsonSchema (165-190)
utils/report-errors.ts (4)
  • MISSED_SPACING_ERROR (33-34)
  • EXTRA_SPACING_ERROR (30-31)
  • GROUP_ORDER_ERROR (27-28)
  • ORDER_ERROR (21-22)
utils/validate-newlines-and-partition-configuration.ts (1)
  • validateNewlinesAndPartitionConfiguration (98-119)
utils/does-custom-group-match.ts (1)
  • doesCustomGroupMatch (121-141)
utils/get-custom-groups-compare-options.ts (1)
  • buildGetCustomGroupOverriddenOptionsFunction (137-148)
rules/sort-heritage-clauses/types.ts (2)
types/common-options.ts (6)
  • CustomGroupsOption (103-140)
  • PartitionByCommentOption (288-303)
  • NewlinesBetweenOption (203-226)
  • GroupsOptions (445-451)
  • CommonOptions (23-73)
  • RegexOption (477-477)
utils/common-json-schemas.ts (1)
  • regexJsonSchema (219-228)
rules/sort-jsx-props/types.ts (2)
types/common-options.ts (1)
  • CustomGroupsOption (103-140)
rules/sort-named-exports/types.ts (3)
  • SingleCustomGroup (74-92)
  • Selector (109-109)
  • allSelectors (155-155)
rules/sort-intersection-types.ts (2)
rules/sort-array-includes.ts (1)
  • defaultOptions (60-74)
rules/sort-union-types/types.ts (1)
  • Options (22-54)
rules/sort-import-attributes.ts (20)
rules/sort-import-attributes/types.ts (1)
  • Options (45-77)
utils/create-eslint-rule.ts (1)
  • createEslintRule (32-35)
utils/is-sortable.ts (1)
  • isSortable (7-9)
utils/get-settings.ts (1)
  • getSettings (91-136)
utils/complete.ts (1)
  • complete (30-36)
utils/validate-custom-sort-configuration.ts (1)
  • validateCustomSortConfiguration (25-35)
utils/validate-generated-groups-configuration.ts (1)
  • validateGeneratedGroupsConfiguration (74-95)
utils/validate-newlines-and-partition-configuration.ts (1)
  • validateNewlinesAndPartitionConfiguration (98-119)
utils/get-eslint-disabled-lines.ts (1)
  • getEslintDisabledLines (45-97)
types/sorting-node.ts (1)
  • SortingNode (18-102)
utils/compute-group.ts (1)
  • computeGroup (75-113)
utils/does-custom-group-match.ts (1)
  • doesCustomGroupMatch (121-141)
utils/is-node-eslint-disabled.ts (1)
  • isNodeEslintDisabled (27-32)
utils/range-to-diff.ts (1)
  • rangeToDiff (32-41)
utils/should-partition.ts (1)
  • shouldPartition (69-95)
utils/sort-nodes-by-groups.ts (1)
  • sortNodesByGroups (106-162)
utils/get-custom-groups-compare-options.ts (1)
  • buildGetCustomGroupOverriddenOptionsFunction (137-148)
utils/report-all-errors.ts (1)
  • reportAllErrors (203-325)
utils/common-json-schemas.ts (5)
  • buildCustomGroupsArrayJsonSchema (302-351)
  • partitionByCommentJsonSchema (241-262)
  • partitionByNewLineJsonSchema (268-272)
  • newlinesBetweenJsonSchema (146-158)
  • groupsJsonSchema (165-190)
utils/report-errors.ts (4)
  • MISSED_SPACING_ERROR (33-34)
  • EXTRA_SPACING_ERROR (30-31)
  • GROUP_ORDER_ERROR (27-28)
  • ORDER_ERROR (21-22)
rules/sort-named-imports/types.ts (1)
types/sorting-node.ts (1)
  • SortingNode (18-102)
test/rules/sort-import-attributes.test.ts (2)
utils/alphabet.ts (1)
  • Alphabet (46-467)
test/utils/validate-rule-json-schema.ts (1)
  • validateRuleJsonSchema (8-19)
rules/sort-export-attributes.ts (18)
rules/sort-export-attributes/types.ts (1)
  • Options (45-77)
utils/create-eslint-rule.ts (1)
  • createEslintRule (32-35)
utils/is-sortable.ts (1)
  • isSortable (7-9)
utils/get-settings.ts (1)
  • getSettings (91-136)
utils/complete.ts (1)
  • complete (30-36)
utils/validate-newlines-and-partition-configuration.ts (1)
  • validateNewlinesAndPartitionConfiguration (98-119)
utils/get-eslint-disabled-lines.ts (1)
  • getEslintDisabledLines (45-97)
types/sorting-node.ts (1)
  • SortingNode (18-102)
utils/compute-group.ts (1)
  • computeGroup (75-113)
utils/does-custom-group-match.ts (1)
  • doesCustomGroupMatch (121-141)
utils/is-node-eslint-disabled.ts (1)
  • isNodeEslintDisabled (27-32)
utils/range-to-diff.ts (1)
  • rangeToDiff (32-41)
utils/should-partition.ts (1)
  • shouldPartition (69-95)
utils/sort-nodes-by-groups.ts (1)
  • sortNodesByGroups (106-162)
utils/get-custom-groups-compare-options.ts (1)
  • buildGetCustomGroupOverriddenOptionsFunction (137-148)
utils/report-all-errors.ts (1)
  • reportAllErrors (203-325)
utils/common-json-schemas.ts (6)
  • commonJsonSchemas (139-140)
  • buildCustomGroupsArrayJsonSchema (302-351)
  • partitionByCommentJsonSchema (241-262)
  • partitionByNewLineJsonSchema (268-272)
  • newlinesBetweenJsonSchema (146-158)
  • groupsJsonSchema (165-190)
utils/report-errors.ts (4)
  • MISSED_SPACING_ERROR (33-34)
  • EXTRA_SPACING_ERROR (30-31)
  • GROUP_ORDER_ERROR (27-28)
  • ORDER_ERROR (21-22)
test/rules/sort-export-attributes.test.ts (2)
utils/alphabet.ts (1)
  • Alphabet (46-467)
test/utils/validate-rule-json-schema.ts (1)
  • validateRuleJsonSchema (8-19)
rules/sort-imports.ts (7)
rules/sort-imports/types.ts (3)
  • Options (29-141)
  • Selector (147-167)
  • Modifier (212-220)
utils/validate-custom-sort-configuration.ts (1)
  • validateCustomSortConfiguration (25-35)
utils/validate-newlines-and-partition-configuration.ts (1)
  • validateNewlinesAndPartitionConfiguration (98-119)
utils/common-json-schemas.ts (1)
  • buildCustomGroupsArrayJsonSchema (302-351)
utils/generate-predefined-groups.ts (1)
  • generatePredefinedGroups (23-56)
utils/compute-group.ts (1)
  • computeGroup (75-113)
utils/does-custom-group-match.ts (1)
  • doesCustomGroupMatch (121-141)
test/rules/sort-imports.test.ts (1)
rules/sort-imports/types.ts (1)
  • Options (29-141)
rules/sort-objects.ts (6)
rules/sort-objects/types.ts (1)
  • Options (25-114)
utils/common-json-schemas.ts (2)
  • regexJsonSchema (219-228)
  • buildCustomGroupsArrayJsonSchema (302-351)
utils/filter-options-by-all-names-match.ts (1)
  • filterOptionsByAllNamesMatch (80-94)
utils/filter-options-by-declaration-comment-matches.ts (1)
  • filterOptionsByDeclarationCommentMatches (14-39)
utils/matches.ts (1)
  • matches (39-60)
rules/sort-objects/get-first-node-parent-with-type.ts (1)
  • getFirstNodeParentWithType (21-46)

Comment on lines +259 to +268
let nodes = formattedMembers.flat()
reportAllErrors<MessageIds>({
sortNodesExcludingEslintDisabled,
availableMessageIds,
sourceCode,
options,
context,
nodes,
})
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Enable spacing diagnostics: pass newlinesBetweenValueGetter.

Many tests assert spacing messages; without this getter, they’ll fail.

Apply:

+import { getLinesBetween } from '../utils/get-lines-between'
@@
   let nodes = formattedMembers.flat()
   reportAllErrors<MessageIds>({
+    newlinesBetweenValueGetter: (left, right) =>
+      getLinesBetween(sourceCode, left, right),
     sortNodesExcludingEslintDisabled,
     availableMessageIds,
     sourceCode,
     options,
     context,
     nodes,
   })
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
let nodes = formattedMembers.flat()
reportAllErrors<MessageIds>({
sortNodesExcludingEslintDisabled,
availableMessageIds,
sourceCode,
options,
context,
nodes,
})
// Add at the top of rules/sort-array-includes.ts
import { getLinesBetween } from '../utils/get-lines-between'
// …
let nodes = formattedMembers.flat()
reportAllErrors<MessageIds>({
newlinesBetweenValueGetter: (left, right) =>
getLinesBetween(sourceCode, left, right),
sortNodesExcludingEslintDisabled,
availableMessageIds,
sourceCode,
options,
context,
nodes,
})
🤖 Prompt for AI Agents
In rules/sort-array-includes.ts around lines 259 to 267, the call to
reportAllErrors is missing the newlinesBetweenValueGetter required for spacing
diagnostics; update the object passed to reportAllErrors to include
newlinesBetweenValueGetter (the existing function/value in this module) so
spacing messages are produced — e.g. add newlinesBetweenValueGetter:
newlinesBetweenValueGetter to the options passed to reportAllErrors.

Comment on lines +25 to +33
it('sorts import attributes', async () => {
await valid({
code: dedent`
export { data } from 'module' with { a: 'a', b: 'b', c: 'c' }
`,
options: [options],
})

await invalid({
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Fix test titles: “import” → “export”

These cases exercise export attributes; the title is misleading.

-    it('sorts import attributes', async () => {
+    it('sorts export attributes', async () => {

Consider updating similar titles throughout this file.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
it('sorts import attributes', async () => {
await valid({
code: dedent`
export { data } from 'module' with { a: 'a', b: 'b', c: 'c' }
`,
options: [options],
})
await invalid({
it('sorts export attributes', async () => {
await valid({
code: dedent`
export { data } from 'module' with { a: 'a', b: 'b', c: 'c' }
`,
options: [options],
})
await invalid({
🤖 Prompt for AI Agents
In test/rules/sort-export-attributes.test.ts around lines 25 to 33, the test
title "sorts import attributes" is incorrect for cases that exercise export
attributes; update the string to "sorts export attributes". Also scan the rest
of this file for any other test titles that say "import" but test
export-attribute behavior and rename them similarly to "export" to keep titles
accurate and consistent.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 42ceb3c and baade3e.

📒 Files selected for processing (3)
  • docs/content/rules/sort-objects.mdx (4 hunks)
  • rules/sort-objects.ts (11 hunks)
  • rules/sort-objects/types.ts (5 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
rules/sort-objects.ts (5)
rules/sort-objects/types.ts (1)
  • Options (25-120)
utils/filter-options-by-all-names-match.ts (1)
  • filterOptionsByAllNamesMatch (80-94)
utils/filter-options-by-declaration-comment-matches.ts (1)
  • filterOptionsByDeclarationCommentMatches (14-39)
utils/matches.ts (1)
  • matches (39-60)
rules/sort-objects/get-first-node-parent-with-type.ts (1)
  • getFirstNodeParentWithType (21-46)
rules/sort-objects/types.ts (1)
types/common-options.ts (2)
  • RegexOption (477-477)
  • CustomGroupsOption (103-140)
🔇 Additional comments (2)
docs/content/rules/sort-objects.mdx (1)

345-362: Anchor the RGB pattern correctly.

'^r|g|b$' still reads as “starts with r” OR “g” OR “ends with b”, so configs copied from here misbehave. Please wrap the alternation in a non-capturing group.

-        allNamesMatchPattern: '^r|g|b$',
+        allNamesMatchPattern: '^(?:r|g|b)$',
rules/sort-objects.ts (1)

561-590: Restore the parent kind discrimination in getObjectParent.

When the object literal sits under a Property, we still fabricate { type: 'VariableDeclarator' }. As a result declarationMatchesPattern/declarationCommentMatchesPattern treat nested properties as top-level declarations, so configs meant for real variable declarators unexpectedly match (e.g. { config: { … } } triggers a ^config$ declaration filter). That is a regression from the old object-map logic and breaks opt-in filtering. Please return the actual parent kind.

-function getObjectParent({
+function getObjectParent({
   onlyFirstParent,
   sourceCode,
   node,
 }: {
   node: TSESTree.ObjectExpression | TSESTree.ObjectPattern
   sourceCode: TSESLint.SourceCode
   onlyFirstParent: boolean
 }):
-  | {
-      node: TSESTree.VariableDeclarator | TSESTree.Property
-      type: 'VariableDeclarator'
-      name: string | null
-    }
+  | {
+      node: TSESTree.VariableDeclarator
+      type: 'VariableDeclarator'
+      name: string | null
+    }
+  | {
+      node: TSESTree.Property
+      type: 'Property'
+      name: string | null
+    }
   | {
       node: TSESTree.CallExpression
       type: 'CallExpression'
       name: string | null
     }
   | null {
   let variableParent = getVariableParent({ onlyFirstParent, node })
   if (variableParent) {
-    return {
-      type: 'VariableDeclarator',
-      name: variableParent.name,
-      node: variableParent.node,
-    }
+    return variableParent.node.type === TSESTree.AST_NODE_TYPES.VariableDeclarator
+      ? {
+          type: 'VariableDeclarator',
+          name: variableParent.name,
+          node: variableParent.node,
+        }
+      : {
+          type: 'Property',
+          name: variableParent.name,
+          node: variableParent.node,
+        }
   }

coderabbitai[bot]

This comment was marked as resolved.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (5)
rules/sort-objects.ts (1)

27-394: Spacing diagnostics missing

This refactor drops the newlinesBetweenValueGetter you previously had wired into reportAllErrors, so the rule no longer reports newline/spacing violations. Restore it (and import getLinesBetween) to keep spacing enforcement alive.

-import {
-  filterOptionsByDeclarationCommentMatches
-} from '../utils/filter-options-by-declaration-comment-matches'
+import {
+  filterOptionsByDeclarationCommentMatches
+} from '../utils/filter-options-by-declaration-comment-matches'
+import { getLinesBetween } from '../utils/get-lines-between'
@@
   reportAllErrors<MessageId>({
     availableMessageIds: {
       missedSpacingBetweenMembers: 'missedSpacingBetweenObjectMembers',
       extraSpacingBetweenMembers: 'extraSpacingBetweenObjectMembers',
       unexpectedDependencyOrder: 'unexpectedObjectsDependencyOrder',
       unexpectedGroupOrder: 'unexpectedObjectsGroupOrder',
       unexpectedOrder: 'unexpectedObjectsOrder',
     },
     sortNodesExcludingEslintDisabled,
     sourceCode,
     options,
     context,
-    nodes,
+    nodes,
+    newlinesBetweenValueGetter: (left, right) =>
+      getLinesBetween(sourceCode, left, right),
   })
test/rules/sort-array-includes.test.ts (3)

1183-1196: Fix spread element quoted as a string ('...foo').

'...foo' is a string literal; should be a spread element to match selector 'spread'. Update both output and code.

Apply:

@@
-          [
-            '...foo',
-            'cFoo',
-            'a',
-          ].includes(value)
+          [
+            ...foo,
+            'cFoo',
+            'a',
+          ].includes(value)
@@
-          [
-            'a',
-            '...foo',
-            'cFoo',
-          ].includes(value)
+          [
+            'a',
+            ...foo,
+            'cFoo',
+          ].includes(value)

Also applies to: 1190-1196


2979-2993: Same issue: spread element quoted as string in “natural/anyOf”.

Replace string '...foo' with spread ...foo in output and code.

Apply:

@@
-          [
-            '...foo',
-            'cFoo',
-            'a',
-          ].includes(value)
+          [
+            ...foo,
+            'cFoo',
+            'a',
+          ].includes(value)
@@
-          [
-            'a',
-            '...foo',
-            'cFoo',
-          ].includes(value)
+          [
+            'a',
+            ...foo,
+            'cFoo',
+          ].includes(value)

Also applies to: 2986-2993


4756-4768: Same issue: spread element quoted as string in “line-length/anyOf”.

Replace string '...foo' with spread ...foo.

Apply:

@@
-          [
-            '...foo',
-            'cFoo',
-            'a',
-          ].includes(value)
+          [
+            ...foo,
+            'cFoo',
+            'a',
+          ].includes(value)
@@
-          [
-            'a',
-            '...foo',
-            'cFoo',
-          ].includes(value)
+          [
+            'a',
+            ...foo,
+            'cFoo',
+          ].includes(value)

Also applies to: 4763-4768

rules/sort-object-types.ts (1)

115-129: Missing TSInterfaceBody visitor for interface support.

The rule currently only visits TSTypeLiteral nodes (type aliases). A past review comment suggested adding a TSInterfaceBody visitor to also sort interface members, and was marked as addressed. However, no TSInterfaceBody visitor is present in the current code.

If interface support is intended, add the missing visitor:

   TSTypeLiteral: node =>
     sortObjectTypeElements<MessageId>({
       availableMessageIds: {
         missedSpacingBetweenMembers: 'missedSpacingBetweenObjectTypeMembers',
         extraSpacingBetweenMembers: 'extraSpacingBetweenObjectTypeMembers',
         unexpectedGroupOrder: 'unexpectedObjectTypesGroupOrder',
         unexpectedOrder: 'unexpectedObjectTypesOrder',
       },
       parentNode:
         node.parent.type === 'TSTypeAliasDeclaration' ? node.parent : null,
       elements: node.members,
       context,
     }),
+  TSInterfaceBody: node =>
+    sortObjectTypeElements<MessageId>({
+      availableMessageIds: {
+        missedSpacingBetweenMembers: 'missedSpacingBetweenObjectTypeMembers',
+        extraSpacingBetweenMembers: 'extraSpacingBetweenObjectTypeMembers',
+        unexpectedGroupOrder: 'unexpectedObjectTypesGroupOrder',
+        unexpectedOrder: 'unexpectedObjectTypesOrder',
+      },
+      parentNode:
+        node.parent?.type === 'TSInterfaceDeclaration' ? node.parent : null,
+      elements: node.body,
+      context,
+    }),
 }),
♻️ Duplicate comments (17)
rules/sort-named-imports/types.ts (1)

94-95: Fix the node type in SortNamedImportsSortingNode.

The type uses TSESTree.ImportClause but sorting nodes are built from TSESTree.ImportSpecifier (see rules/sort-named-imports.ts:136 where node: specifier is assigned and specifier is filtered by type === 'ImportSpecifier').

Apply this fix:

-/** Extended sorting node for named import specifiers. */
-export type SortNamedImportsSortingNode = SortingNode<TSESTree.ImportClause>
+/** Extended sorting node for named import specifiers. */
+export type SortNamedImportsSortingNode = SortingNode<TSESTree.ImportSpecifier>
docs/content/rules/sort-decorators.mdx (3)

255-262: Document the full newlinesBetween type union.

The type annotation shows only number | 'ignore', but the implementation and tests support 'always' and 'never' as well. Update the type annotation and bullet descriptions to include all valid values.

Apply this diff:

-<sub>type: `number | 'ignore'`</sub>
+<sub>type: `'always' | 'never' | number | 'ignore'`</sub>
 <sub>default: `'ignore'`</sub>
 
 Specifies how to handle newlines between groups.
 
 - `'ignore'` — Do not report errors related to newlines.
-- `0` — No newlines are allowed.
-- Any other number — Enforce this number of newlines between each group, and forbid newlines inside groups.
+- `'always'` — Require exactly one blank line between groups.
+- `'never'` — Disallow blank lines between groups.
+- `number` — Require exactly this number of blank lines between groups; forbid blank lines inside groups.

352-359: Correct CustomGroupDefinition type annotations.

The fallbackSort.type should be a specific union (not string), and newlinesInside should accept 'always' | 'never' | number to match the implementation.

Apply this diff:

 interface CustomGroupDefinition {
   groupName: string
   type?: 'alphabetical' | 'natural' | 'line-length' | 'unsorted'
   order?: 'asc' | 'desc'
-  fallbackSort?: { type: string; order?: 'asc' | 'desc' }
-  newlinesInside?: number
+  fallbackSort?: {
+    type: 'alphabetical' | 'natural' | 'line-length' | 'custom' | 'unsorted'
+    order?: 'asc' | 'desc'
+  }
+  newlinesInside?: 'always' | 'never' | number
   selector?: string
   elementNamePattern?: string | string[] | { pattern: string; flags?: string } | { pattern: string; flags?: string }[]
 }

367-378: Correct CustomGroupAnyOfDefinition type annotations.

Same issues as CustomGroupDefinition: fallbackSort.type should be a specific union, and newlinesInside should accept 'always' | 'never' | number.

Apply this diff:

 interface CustomGroupAnyOfDefinition {
   groupName: string
   type?: 'alphabetical' | 'natural' | 'line-length' | 'unsorted'
   order?: 'asc' | 'desc'
-  fallbackSort?: { type: string; order?: 'asc' | 'desc' }
-  newlinesInside?: number
+  fallbackSort?: {
+    type: 'alphabetical' | 'natural' | 'line-length' | 'custom' | 'unsorted'
+    order?: 'asc' | 'desc'
+  }
+  newlinesInside?: 'always' | 'never' | number
   anyOf: Array<{
       selector?: string
       elementNamePattern?: string | string[] | { pattern: string; flags?: string } | { pattern: string; flags?: string }[]
   }>
 }
docs/content/rules/sort-heritage-clauses.mdx (5)

152-159: Fix terminology and optional flags in RegExpPattern.

The documentation incorrectly references "class decorators" (should be "heritage clauses"), and flags should be optional in the RegExpPattern type definition to match the actual interface.

Apply this diff:

-Enables the use of comments to separate class decorators into logical groups.
+Enables the use of comments to separate heritage clauses into logical groups.

 - `true` — All comments will be treated as delimiters, creating partitions.
 - `false` — Comments will not be used as delimiters.
-- `RegExpPattern = string | { pattern: string; flags: string}` — A regexp pattern to specify which comments should act as delimiters.
+- `RegExpPattern = string | { pattern: string; flags?: string }` — A regexp pattern to specify which comments should act as delimiters.
 - `RegExpPattern[]` — A list of regexp patterns to specify which comments should act as delimiters.
 - `{ block: boolean | RegExpPattern | RegExpPattern[]; line: boolean | RegExpPattern | RegExpPattern[] }` — Specify which block and line comments should act as delimiters.

168-176: Document full newlinesBetween type union.

The type annotation shows only number | 'ignore', but should include 'always' and 'never' to match the implementation.

Apply this diff:

-<sub>type: `number | 'ignore'`</sub>
+<sub>type: `'always' | 'never' | number | 'ignore'`</sub>
 <sub>default: `'ignore'`</sub>
 
 Specifies how to handle newlines between groups.
 
 - `'ignore'` — Do not report errors related to newlines.
-- `0` — No newlines are allowed.
-- Any other number — Enforce this number of newlines between each group, and forbid newlines inside groups.
+- `'always'` — Require exactly one blank line between groups.
+- `'never'` — Disallow blank lines between groups.
+- `number` — Require exactly this number of blank lines between groups; forbid blank lines inside groups.

265-273: Correct CustomGroupDefinition type annotations.

Include 'custom' in the type union, use a specific union for fallbackSort.type (not string), and expand newlinesInside to accept 'always' | 'never' | number.

Apply this diff:

 interface CustomGroupDefinition {
   groupName: string
-  type?: 'alphabetical' | 'natural' | 'line-length' | 'unsorted'
+  type?: 'alphabetical' | 'natural' | 'line-length' | 'custom' | 'unsorted'
   order?: 'asc' | 'desc'
-  fallbackSort?: { type: string; order?: 'asc' | 'desc' }
-  newlinesInside?: number
+  fallbackSort?: {
+    type: 'alphabetical' | 'natural' | 'line-length' | 'custom' | 'unsorted'
+    order?: 'asc' | 'desc'
+  }
+  newlinesInside?: 'always' | 'never' | number
   elementNamePattern?: string | string[] | { pattern: string; flags?: string } | { pattern: string; flags?: string }[]
 }

280-291: Correct CustomGroupAnyOfDefinition type annotations.

Same issues as CustomGroupDefinition: include 'custom' in type, use a specific union for fallbackSort.type, and expand newlinesInside.

Apply this diff:

 interface CustomGroupAnyOfDefinition {
   groupName: string
-  type?: 'alphabetical' | 'natural' | 'line-length' | 'unsorted'
+  type?: 'alphabetical' | 'natural' | 'line-length' | 'custom' | 'unsorted'
   order?: 'asc' | 'desc'
-  fallbackSort?: { type: string; order?: 'asc' | 'desc' }
-  newlinesInside?: number
+  fallbackSort?: {
+    type: 'alphabetical' | 'natural' | 'line-length' | 'custom' | 'unsorted'
+    order?: 'asc' | 'desc'
+  }
+  newlinesInside?: 'always' | 'never' | number
   anyOf: Array<{
       selector?: string
       elementNamePattern?: string | string[] | { pattern: string; flags?: string } | { pattern: string; flags?: string }[]
   }>
 }

295-302: Document the 'selector' attribute.

The CustomGroupAnyOfDefinition interface includes a selector? field in the anyOf items, but it's not documented in the Attributes section.

Apply this diff:

 #### Attributes
 
 - `groupName` — The group's name, which needs to be put in the [`groups`](#groups) option.
+- `selector` — (AnyOf only) AST selector to narrow matching elements for this group item.
 - `elementNamePattern` — If entered, will check that the name of the element matches the pattern entered.
 - `type` — Overrides the [`type`](#type) option for that custom group. `unsorted` will not sort the group.
 - `order` — Overrides the [`order`](#order) option for that custom group.
 - `fallbackSort` — Overrides the [`fallbackSort`](#fallbacksort) option for that custom group.
 - `newlinesInside` — Enforces a specific newline behavior between elements of the group.
rules/sort-heritage-clauses.ts (1)

193-205: Still missing newlinesBetweenValueGetter.

We now emit spacing message IDs but the reportAllErrors call still omits newlinesBetweenValueGetter. Without it, spacing violations are never detected, so the new messages will never fire. Please wire it back in and import getLinesBetween.

 import { reportAllErrors } from '../utils/report-all-errors'
+import { getLinesBetween } from '../utils/get-lines-between'
@@
-    reportAllErrors<MessageId>({
+    reportAllErrors<MessageId>({
       availableMessageIds: {
         missedSpacingBetweenMembers: 'missedSpacingBetweenHeritageClauses',
         extraSpacingBetweenMembers: 'extraSpacingBetweenHeritageClauses',
         unexpectedGroupOrder: 'unexpectedHeritageClausesGroupOrder',
         unexpectedOrder: 'unexpectedHeritageClausesOrder',
       },
+      newlinesBetweenValueGetter: (left, right) =>
+        getLinesBetween(sourceCode, left, right),
       sortNodesExcludingEslintDisabled:
         createSortNodesExcludingEslintDisabled(nodes),
       sourceCode,
       options,
       context,
       nodes,
     })
rules/sort-array-includes.ts (1)

33-267: Spacing diagnostics still disabled

reportAllErrors can’t emit newline/spacing violations without a newlinesBetweenValueGetter. That omission was raised earlier and remains unresolved, so spacing regressions will slip past linting. Please wire it back in.

@@
-import {
-  filterOptionsByAllNamesMatch
-} from '../utils/filter-options-by-all-names-match'
+import {
+  filterOptionsByAllNamesMatch
+} from '../utils/filter-options-by-all-names-match'
+import { getLinesBetween } from '../utils/get-lines-between'
@@
   reportAllErrors<MessageIds>({
     sortNodesExcludingEslintDisabled,
     availableMessageIds,
     sourceCode,
     options,
     context,
-    nodes,
+    nodes,
+    newlinesBetweenValueGetter: (left, right) =>
+      getLinesBetween(sourceCode, left, right),
   })
test/rules/sort-imports.test.ts (1)

4311-4316: Fix ESLint no-unsafe-call on dedent (repeat of prior note)

Add a one-line disable before the tagged template uses here to silence @typescript-eslint/no-unsafe-call in this test file.

Apply:

-        code: dedent`
+        // eslint-disable-next-line @typescript-eslint/no-unsafe-call
+        code: dedent`
...
-        output: dedent`
+        // eslint-disable-next-line @typescript-eslint/no-unsafe-call
+        output: dedent`
...
-        code: dedent`
+        // eslint-disable-next-line @typescript-eslint/no-unsafe-call
+        code: dedent`

(Longer‑term: consider ts-dedent or dedent(String.raw...) in tests.)

Also applies to: 4349-4355, 4361-4367

rules/sort-import-attributes.ts (1)

149-162: Missing newlinesBetweenValueGetter in reportAllErrors call.

The reportAllErrors call is missing the newlinesBetweenValueGetter parameter, which prevents spacing diagnostics (missedSpacingBetweenImportAttributes and extraSpacingBetweenImportAttributes) from working correctly.

Add the missing parameter:

+import { getLinesBetween } from '../utils/get-lines-between'
+
 // ... existing code ...

         reportAllErrors<MessageId>({
           availableMessageIds: {
             missedSpacingBetweenMembers: 'missedSpacingBetweenImportAttributes',
             extraSpacingBetweenMembers: 'extraSpacingBetweenImportAttributes',
             unexpectedGroupOrder: 'unexpectedImportAttributesGroupOrder',
             unexpectedOrder: 'unexpectedImportAttributesOrder',
           },
+          newlinesBetweenValueGetter: (left, right) =>
+            getLinesBetween(sourceCode, left, right),
           sortNodesExcludingEslintDisabled:
             createSortNodesExcludingEslintDisabled(nodes),
           sourceCode,
           options,
           context,
           nodes,
         })
rules/sort-jsx-props.ts (1)

189-203: Enable spacing diagnostics: pass newlinesBetweenValueGetter.

Without it, missed/extra newline errors won’t be reported for JSX props.

Apply:

+import { getLinesBetween } from '../utils/get-lines-between'
@@
         reportAllErrors<MessageId>({
           availableMessageIds: {
             missedSpacingBetweenMembers: 'missedSpacingBetweenJSXPropsMembers',
             extraSpacingBetweenMembers: 'extraSpacingBetweenJSXPropsMembers',
             unexpectedGroupOrder: 'unexpectedJSXPropsGroupOrder',
             unexpectedOrder: 'unexpectedJSXPropsOrder',
           },
+          newlinesBetweenValueGetter: (left, right) =>
+            getLinesBetween(sourceCode, left, right),
           sortNodesExcludingEslintDisabled:
             createSortNodesExcludingEslintDisabled(currentNodes),
           nodes: currentNodes,
           sourceCode,
           options,
           context,
         })
rules/sort-jsx-props/types.ts (1)

100-105: Selector narrowed to 'prop': update stale JSDoc and clarify usage.

Selector is only 'prop'. Use modifiers ('shorthand' | 'multiline') for specificity.

Apply:

@@
-  /**
-   * The selector type for this group. Can be 'prop' for regular props,
-   * 'multiline' for multi-line props, or 'shorthand' for shorthand props.
-   */
+  /**
+   * The selector type for this group. Allowed: 'prop' only.
+   * Use modifiers ('shorthand' | 'multiline') to target those cases.
+   */
   selector?: Selector
@@
-/**
- * Union type of all available JSX prop selectors. Used to categorize different
- * types of JSX props.
- */
+/**
+ * Selector for JSX props. Only "prop" is supported; specificity is via modifiers.
+ */
 export type Selector = PropertySelector
@@
-/**
- * Complete list of available JSX prop selectors. Used for validation and JSON
- * schema generation.
- */
+/** Supported JSX prop selectors for validation and schema generation. */
 export let allSelectors: Selector[] = ['prop']

Also applies to: 113-118, 146-153

rules/sort-object-types.ts (2)

328-336: Pass newlinesBetweenValueGetter to enable spacing diagnostics.

Without newlinesBetweenValueGetter, reportAllErrors cannot compute missed/extra blank-line errors when options.newlinesBetween is set.

Apply this diff:

 reportAllErrors<MessageIds>({
   sortNodesExcludingEslintDisabled,
+  newlinesBetweenValueGetter: (left, right) =>
+    getLinesBetween(sourceCode, left, right),
   availableMessageIds,
   sourceCode,
   options,
   context,
   nodes,
 })

Add the missing import at the top of the file:

+import { getLinesBetween } from '../utils/get-lines-between'

234-238: Don't assign optional/required modifiers to index signatures.

Index signatures don't support optionality; adding 'required' causes misleading predefined groups (e.g., required-index-signature).

Apply:

-  if (isMemberOptional(typeElement)) {
-    modifiers.push('optional')
-  } else {
-    modifiers.push('required')
-  }
+  if (typeElement.type !== 'TSIndexSignature') {
+    if (isMemberOptional(typeElement)) {
+      modifiers.push('optional')
+    } else {
+      modifiers.push('required')
+    }
+  }
🧹 Nitpick comments (4)
test/rules/sort-enums.test.ts (3)

66-107: Test name may be misleading after key type change.

The test is named "sorts enum members with number keys" but now uses string-literal keys ('1', '12', '2', '8') instead of numeric keys. This tests alphabetical sorting of string keys that contain numeric characters, not numeric key sorting.

Consider either:

  1. Renaming to "sorts enum members with string number keys" or "sorts enum members with numeric string keys"
  2. Or if the intent is to test actual numeric keys, reverting to numeric keys: 1, 12, 2, 8

The expected alphabetical order '1', '12', '2', '8' is correct for string sorting (where '12' comes before '2' because '1' < '2'), but may be counterintuitive for readers expecting numeric ordering.


1625-1666: Test name may be misleading after key type change.

Same concern as the alphabetical test: the test is named "sorts enum members with number keys" but uses string-literal keys ('1', '2', '8', '12').

Consider renaming for clarity, or using actual numeric keys if that's the intent.

The expected natural sort order '1', '2', '8', '12' is correct (natural sort correctly handles numeric strings), but the test name should reflect that these are string keys.


3184-3225: Test name may be misleading after key type change.

Same concern as previous tests: the test is named "sorts enum members with number keys" but uses string-literal keys ('12', '1', '2', '8').

Consider renaming for clarity, or using actual numeric keys if that's the intent.

The expected line-length order is correct ('12' has 4 characters including quotes, while others have 3).

test/rules/sort-imports.test.ts (1)

2431-2437: Reset spies after tsconfig stubs to avoid cross-test leakage

Add after: vi.resetAllMocks() in these tests that vi.spyOn readClosestTsConfigByPath to keep tests isolated.

Apply:

         before: () => {
           mockReadClosestTsConfigByPathWith({
             paths: {
               $path: ['./path'],
             },
           })
         },
+        after: () => {
+          vi.resetAllMocks()
+        },

(Apply similarly in the other two tests shown in the selected ranges.)

Also applies to: 6082-6088, 9767-9773

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between fa55de3 and 8c3bcb5.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml, !pnpm-lock.yaml
📒 Files selected for processing (67)
  • docs/content/rules/sort-array-includes.mdx (3 hunks)
  • docs/content/rules/sort-decorators.mdx (5 hunks)
  • docs/content/rules/sort-export-attributes.mdx (1 hunks)
  • docs/content/rules/sort-exports.mdx (0 hunks)
  • docs/content/rules/sort-heritage-clauses.mdx (5 hunks)
  • docs/content/rules/sort-import-attributes.mdx (1 hunks)
  • docs/content/rules/sort-imports.mdx (1 hunks)
  • docs/content/rules/sort-interfaces.mdx (3 hunks)
  • docs/content/rules/sort-intersection-types.mdx (1 hunks)
  • docs/content/rules/sort-jsx-props.mdx (3 hunks)
  • docs/content/rules/sort-named-exports.mdx (0 hunks)
  • docs/content/rules/sort-named-imports.mdx (0 hunks)
  • docs/content/rules/sort-object-types.mdx (3 hunks)
  • docs/content/rules/sort-objects.mdx (4 hunks)
  • docs/content/rules/sort-sets.mdx (3 hunks)
  • docs/public/llms.txt (1 hunks)
  • index.ts (4 hunks)
  • package.json (4 hunks)
  • readme.md (1 hunks)
  • rules/sort-array-includes.ts (5 hunks)
  • rules/sort-array-includes/types.ts (0 hunks)
  • rules/sort-classes.ts (1 hunks)
  • rules/sort-decorators.ts (6 hunks)
  • rules/sort-decorators/types.ts (1 hunks)
  • rules/sort-enums.ts (5 hunks)
  • rules/sort-export-attributes.ts (1 hunks)
  • rules/sort-export-attributes/types.ts (1 hunks)
  • rules/sort-exports.ts (2 hunks)
  • rules/sort-exports/types.ts (0 hunks)
  • rules/sort-heritage-clauses.ts (6 hunks)
  • rules/sort-heritage-clauses/types.ts (1 hunks)
  • rules/sort-import-attributes.ts (1 hunks)
  • rules/sort-import-attributes/types.ts (1 hunks)
  • rules/sort-imports.ts (6 hunks)
  • rules/sort-imports/types.ts (1 hunks)
  • rules/sort-interfaces.ts (2 hunks)
  • rules/sort-intersection-types.ts (1 hunks)
  • rules/sort-jsx-props.ts (6 hunks)
  • rules/sort-jsx-props/types.ts (4 hunks)
  • rules/sort-maps.ts (3 hunks)
  • rules/sort-modules.ts (2 hunks)
  • rules/sort-named-exports.ts (2 hunks)
  • rules/sort-named-exports/types.ts (1 hunks)
  • rules/sort-named-imports.ts (2 hunks)
  • rules/sort-named-imports/types.ts (1 hunks)
  • rules/sort-object-types.ts (9 hunks)
  • rules/sort-object-types/get-custom-groups-compare-options.ts (3 hunks)
  • rules/sort-object-types/types.ts (3 hunks)
  • rules/sort-objects.ts (11 hunks)
  • rules/sort-objects/types.ts (5 hunks)
  • rules/sort-switch-case.ts (2 hunks)
  • rules/sort-union-types.ts (1 hunks)
  • rules/sort-variable-declarations.ts (1 hunks)
  • test/rules/sort-array-includes.test.ts (12 hunks)
  • test/rules/sort-decorators.test.ts (2 hunks)
  • test/rules/sort-enums.test.ts (6 hunks)
  • test/rules/sort-export-attributes.test.ts (1 hunks)
  • test/rules/sort-exports.test.ts (0 hunks)
  • test/rules/sort-heritage-clauses.test.ts (5 hunks)
  • test/rules/sort-import-attributes.test.ts (1 hunks)
  • test/rules/sort-imports.test.ts (25 hunks)
  • test/rules/sort-interfaces.test.ts (16 hunks)
  • test/rules/sort-jsx-props.test.ts (35 hunks)
  • test/rules/sort-named-exports.test.ts (6 hunks)
  • test/rules/sort-named-imports.test.ts (6 hunks)
  • test/rules/sort-object-types.test.ts (19 hunks)
  • test/rules/sort-object-types/get-custom-groups-compare-options.test.ts (1 hunks)
💤 Files with no reviewable changes (6)
  • docs/content/rules/sort-named-exports.mdx
  • test/rules/sort-exports.test.ts
  • rules/sort-array-includes/types.ts
  • rules/sort-exports/types.ts
  • docs/content/rules/sort-exports.mdx
  • docs/content/rules/sort-named-imports.mdx
🚧 Files skipped from review as they are similar to previous changes (20)
  • rules/sort-named-exports/types.ts
  • rules/sort-classes.ts
  • rules/sort-variable-declarations.ts
  • rules/sort-maps.ts
  • rules/sort-object-types/get-custom-groups-compare-options.ts
  • readme.md
  • test/rules/sort-import-attributes.test.ts
  • docs/content/rules/sort-array-includes.mdx
  • rules/sort-import-attributes/types.ts
  • docs/content/rules/sort-import-attributes.mdx
  • test/rules/sort-named-exports.test.ts
  • rules/sort-decorators/types.ts
  • rules/sort-export-attributes/types.ts
  • test/rules/sort-export-attributes.test.ts
  • test/rules/sort-object-types/get-custom-groups-compare-options.test.ts
  • rules/sort-modules.ts
  • docs/content/rules/sort-object-types.mdx
  • rules/sort-switch-case.ts
  • docs/content/rules/sort-objects.mdx
  • docs/content/rules/sort-export-attributes.mdx
🧰 Additional context used
🧬 Code graph analysis (23)
rules/sort-union-types.ts (2)
rules/sort-array-includes.ts (1)
  • defaultOptions (60-74)
rules/sort-union-types/types.ts (1)
  • Options (22-54)
rules/sort-intersection-types.ts (2)
rules/sort-array-includes.ts (1)
  • defaultOptions (60-74)
rules/sort-union-types/types.ts (1)
  • Options (22-54)
rules/sort-imports/types.ts (1)
types/common-options.ts (1)
  • CustomGroupsOption (103-140)
rules/sort-object-types/types.ts (3)
types/common-options.ts (3)
  • RegexOption (477-477)
  • CustomGroupsOption (103-140)
  • FallbackSortOption (319-331)
rules/sort-objects/types.ts (1)
  • SingleCustomGroup (128-144)
types/join-with-dash.ts (1)
  • JoinWithDash (4-4)
rules/sort-named-exports.ts (5)
rules/sort-array-includes.ts (1)
  • defaultOptions (60-74)
rules/sort-named-exports/types.ts (1)
  • Options (26-66)
utils/sort-nodes-by-groups.ts (1)
  • sortNodesByGroups (106-162)
utils/get-custom-groups-compare-options.ts (1)
  • buildGetCustomGroupOverriddenOptionsFunction (137-148)
utils/report-all-errors.ts (1)
  • reportAllErrors (203-325)
rules/sort-decorators.ts (6)
rules/sort-decorators/types.ts (1)
  • Options (16-29)
utils/common-json-schemas.ts (4)
  • buildCustomGroupsArrayJsonSchema (302-351)
  • partitionByNewLineJsonSchema (268-272)
  • newlinesBetweenJsonSchema (146-158)
  • groupsJsonSchema (165-190)
utils/report-errors.ts (4)
  • MISSED_SPACING_ERROR (33-34)
  • EXTRA_SPACING_ERROR (30-31)
  • GROUP_ORDER_ERROR (27-28)
  • ORDER_ERROR (21-22)
utils/validate-newlines-and-partition-configuration.ts (1)
  • validateNewlinesAndPartitionConfiguration (98-119)
utils/does-custom-group-match.ts (1)
  • doesCustomGroupMatch (121-141)
utils/get-custom-groups-compare-options.ts (1)
  • buildGetCustomGroupOverriddenOptionsFunction (137-148)
rules/sort-array-includes.ts (5)
types/sorting-node.ts (1)
  • SortingNode (18-102)
rules/sort-array-includes/types.ts (2)
  • Options (24-68)
  • Selector (100-100)
utils/filter-options-by-all-names-match.ts (1)
  • filterOptionsByAllNamesMatch (80-94)
utils/sort-nodes-by-groups.ts (1)
  • sortNodesByGroups (106-162)
utils/get-custom-groups-compare-options.ts (1)
  • buildGetCustomGroupOverriddenOptionsFunction (137-148)
rules/sort-objects/types.ts (1)
types/common-options.ts (2)
  • RegexOption (477-477)
  • CustomGroupsOption (103-140)
rules/sort-object-types.ts (5)
rules/sort-array-includes.ts (1)
  • defaultOptions (60-74)
rules/sort-object-types/types.ts (1)
  • Options (28-106)
utils/filter-options-by-all-names-match.ts (1)
  • filterOptionsByAllNamesMatch (80-94)
utils/filter-options-by-declaration-comment-matches.ts (1)
  • filterOptionsByDeclarationCommentMatches (14-39)
utils/matches.ts (1)
  • matches (39-60)
rules/sort-heritage-clauses/types.ts (2)
types/common-options.ts (6)
  • CustomGroupsOption (103-140)
  • PartitionByCommentOption (288-303)
  • NewlinesBetweenOption (203-226)
  • GroupsOptions (445-451)
  • CommonOptions (23-73)
  • RegexOption (477-477)
utils/common-json-schemas.ts (1)
  • regexJsonSchema (219-228)
rules/sort-import-attributes.ts (19)
rules/sort-import-attributes/types.ts (1)
  • Options (45-77)
utils/create-eslint-rule.ts (1)
  • createEslintRule (32-35)
utils/is-sortable.ts (1)
  • isSortable (7-9)
utils/get-settings.ts (1)
  • getSettings (91-136)
utils/complete.ts (1)
  • complete (30-36)
utils/validate-custom-sort-configuration.ts (1)
  • validateCustomSortConfiguration (25-35)
utils/validate-generated-groups-configuration.ts (1)
  • validateGeneratedGroupsConfiguration (74-95)
utils/validate-newlines-and-partition-configuration.ts (1)
  • validateNewlinesAndPartitionConfiguration (98-119)
utils/get-eslint-disabled-lines.ts (1)
  • getEslintDisabledLines (45-97)
utils/compute-group.ts (1)
  • computeGroup (75-113)
utils/does-custom-group-match.ts (1)
  • doesCustomGroupMatch (121-141)
utils/is-node-eslint-disabled.ts (1)
  • isNodeEslintDisabled (27-32)
utils/range-to-diff.ts (1)
  • rangeToDiff (32-41)
utils/should-partition.ts (1)
  • shouldPartition (69-95)
utils/sort-nodes-by-groups.ts (1)
  • sortNodesByGroups (106-162)
utils/get-custom-groups-compare-options.ts (1)
  • buildGetCustomGroupOverriddenOptionsFunction (137-148)
utils/report-all-errors.ts (1)
  • reportAllErrors (203-325)
utils/common-json-schemas.ts (6)
  • commonJsonSchemas (139-140)
  • buildCustomGroupsArrayJsonSchema (302-351)
  • partitionByCommentJsonSchema (241-262)
  • partitionByNewLineJsonSchema (268-272)
  • newlinesBetweenJsonSchema (146-158)
  • groupsJsonSchema (165-190)
utils/report-errors.ts (4)
  • MISSED_SPACING_ERROR (33-34)
  • EXTRA_SPACING_ERROR (30-31)
  • GROUP_ORDER_ERROR (27-28)
  • ORDER_ERROR (21-22)
rules/sort-objects.ts (5)
rules/sort-objects/types.ts (1)
  • Options (25-120)
utils/common-json-schemas.ts (1)
  • regexJsonSchema (219-228)
utils/filter-options-by-all-names-match.ts (1)
  • filterOptionsByAllNamesMatch (80-94)
utils/filter-options-by-declaration-comment-matches.ts (1)
  • filterOptionsByDeclarationCommentMatches (14-39)
utils/matches.ts (1)
  • matches (39-60)
rules/sort-jsx-props/types.ts (2)
types/common-options.ts (1)
  • CustomGroupsOption (103-140)
rules/sort-named-exports/types.ts (3)
  • SingleCustomGroup (74-92)
  • Selector (109-109)
  • allSelectors (155-155)
rules/sort-heritage-clauses.ts (10)
utils/common-json-schemas.ts (4)
  • buildCustomGroupsArrayJsonSchema (302-351)
  • partitionByNewLineJsonSchema (268-272)
  • partitionByCommentJsonSchema (241-262)
  • newlinesBetweenJsonSchema (146-158)
utils/report-errors.ts (4)
  • MISSED_SPACING_ERROR (33-34)
  • EXTRA_SPACING_ERROR (30-31)
  • GROUP_ORDER_ERROR (27-28)
  • ORDER_ERROR (21-22)
utils/validate-newlines-and-partition-configuration.ts (1)
  • validateNewlinesAndPartitionConfiguration (98-119)
types/sorting-node.ts (1)
  • SortingNode (18-102)
utils/compute-group.ts (1)
  • computeGroup (75-113)
utils/does-custom-group-match.ts (1)
  • doesCustomGroupMatch (121-141)
utils/should-partition.ts (1)
  • shouldPartition (69-95)
utils/sort-nodes-by-groups.ts (1)
  • sortNodesByGroups (106-162)
utils/get-custom-groups-compare-options.ts (1)
  • buildGetCustomGroupOverriddenOptionsFunction (137-148)
utils/report-all-errors.ts (1)
  • reportAllErrors (203-325)
rules/sort-named-imports/types.ts (1)
types/sorting-node.ts (1)
  • SortingNode (18-102)
rules/sort-export-attributes.ts (22)
rules/sort-imports.ts (1)
  • MessageId (59-65)
rules/sort-array-includes.ts (1)
  • defaultOptions (60-74)
rules/sort-export-attributes/types.ts (1)
  • Options (45-77)
utils/create-eslint-rule.ts (1)
  • createEslintRule (32-35)
utils/is-sortable.ts (1)
  • isSortable (7-9)
utils/get-settings.ts (1)
  • getSettings (91-136)
utils/complete.ts (1)
  • complete (30-36)
utils/validate-custom-sort-configuration.ts (1)
  • validateCustomSortConfiguration (25-35)
utils/validate-generated-groups-configuration.ts (1)
  • validateGeneratedGroupsConfiguration (74-95)
utils/validate-newlines-and-partition-configuration.ts (1)
  • validateNewlinesAndPartitionConfiguration (98-119)
utils/get-eslint-disabled-lines.ts (1)
  • getEslintDisabledLines (45-97)
types/sorting-node.ts (1)
  • SortingNode (18-102)
utils/compute-group.ts (1)
  • computeGroup (75-113)
utils/does-custom-group-match.ts (1)
  • doesCustomGroupMatch (121-141)
utils/is-node-eslint-disabled.ts (1)
  • isNodeEslintDisabled (27-32)
utils/range-to-diff.ts (1)
  • rangeToDiff (32-41)
utils/should-partition.ts (1)
  • shouldPartition (69-95)
utils/sort-nodes-by-groups.ts (1)
  • sortNodesByGroups (106-162)
utils/get-custom-groups-compare-options.ts (1)
  • buildGetCustomGroupOverriddenOptionsFunction (137-148)
utils/report-all-errors.ts (1)
  • reportAllErrors (203-325)
utils/common-json-schemas.ts (6)
  • commonJsonSchemas (139-140)
  • buildCustomGroupsArrayJsonSchema (302-351)
  • partitionByCommentJsonSchema (241-262)
  • partitionByNewLineJsonSchema (268-272)
  • newlinesBetweenJsonSchema (146-158)
  • groupsJsonSchema (165-190)
utils/report-errors.ts (4)
  • MISSED_SPACING_ERROR (33-34)
  • EXTRA_SPACING_ERROR (30-31)
  • GROUP_ORDER_ERROR (27-28)
  • ORDER_ERROR (21-22)
test/rules/sort-imports.test.ts (1)
rules/sort-imports/types.ts (1)
  • Options (29-141)
rules/sort-jsx-props.ts (5)
rules/sort-array-includes.ts (1)
  • defaultOptions (60-74)
rules/sort-jsx-props/types.ts (1)
  • Options (24-65)
utils/common-json-schemas.ts (1)
  • buildCustomGroupsArrayJsonSchema (302-351)
utils/filter-options-by-all-names-match.ts (1)
  • filterOptionsByAllNamesMatch (80-94)
utils/matches.ts (1)
  • matches (39-60)
rules/sort-exports.ts (5)
types/sorting-node.ts (1)
  • SortingNode (18-102)
rules/sort-array-includes.ts (1)
  • defaultOptions (60-74)
rules/sort-exports/types.ts (1)
  • Options (25-57)
utils/sort-nodes-by-groups.ts (1)
  • sortNodesByGroups (106-162)
utils/report-all-errors.ts (1)
  • reportAllErrors (203-325)
rules/sort-interfaces.ts (2)
rules/sort-array-includes.ts (1)
  • defaultOptions (60-74)
rules/sort-objects/types.ts (1)
  • Options (25-120)
rules/sort-enums.ts (2)
rules/sort-enums/types.ts (1)
  • Options (20-68)
utils/common-json-schemas.ts (1)
  • buildCustomGroupsArrayJsonSchema (302-351)
rules/sort-imports.ts (7)
rules/sort-imports/types.ts (3)
  • Options (29-141)
  • Selector (147-167)
  • Modifier (212-220)
utils/validate-newlines-and-partition-configuration.ts (1)
  • validateNewlinesAndPartitionConfiguration (98-119)
rules/sort-imports/validate-side-effects-configuration.ts (1)
  • validateSideEffectsConfiguration (19-48)
utils/common-json-schemas.ts (1)
  • buildCustomGroupsArrayJsonSchema (302-351)
utils/generate-predefined-groups.ts (1)
  • generatePredefinedGroups (23-56)
utils/compute-group.ts (1)
  • computeGroup (75-113)
utils/does-custom-group-match.ts (1)
  • doesCustomGroupMatch (121-141)
rules/sort-named-imports.ts (4)
rules/sort-named-imports/types.ts (1)
  • Options (26-66)
utils/sort-nodes-by-groups.ts (1)
  • sortNodesByGroups (106-162)
utils/get-custom-groups-compare-options.ts (1)
  • buildGetCustomGroupOverriddenOptionsFunction (137-148)
utils/report-all-errors.ts (1)
  • reportAllErrors (203-325)

Comment on lines 7 to 162
import {
buildCustomGroupsArrayJsonSchema,
partitionByCommentJsonSchema,
partitionByNewLineJsonSchema,
newlinesBetweenJsonSchema,
commonJsonSchemas,
groupsJsonSchema,
} from '../utils/common-json-schemas'
import {
MISSED_SPACING_ERROR,
EXTRA_SPACING_ERROR,
GROUP_ORDER_ERROR,
ORDER_ERROR,
} from '../utils/report-errors'
import { validateNewlinesAndPartitionConfiguration } from '../utils/validate-newlines-and-partition-configuration'
import { buildGetCustomGroupOverriddenOptionsFunction } from '../utils/get-custom-groups-compare-options'
import { validateGeneratedGroupsConfiguration } from '../utils/validate-generated-groups-configuration'
import { validateCustomSortConfiguration } from '../utils/validate-custom-sort-configuration'
import { singleCustomGroupJsonSchema } from './sort-export-attributes/types'
import { getEslintDisabledLines } from '../utils/get-eslint-disabled-lines'
import { isNodeEslintDisabled } from '../utils/is-node-eslint-disabled'
import { doesCustomGroupMatch } from '../utils/does-custom-group-match'
import { sortNodesByGroups } from '../utils/sort-nodes-by-groups'
import { createEslintRule } from '../utils/create-eslint-rule'
import { reportAllErrors } from '../utils/report-all-errors'
import { shouldPartition } from '../utils/should-partition'
import { computeGroup } from '../utils/compute-group'
import { rangeToDiff } from '../utils/range-to-diff'
import { getSettings } from '../utils/get-settings'
import { isSortable } from '../utils/is-sortable'
import { complete } from '../utils/complete'

type MessageId =
| 'missedSpacingBetweenExportAttributes'
| 'unexpectedExportAttributesGroupOrder'
| 'extraSpacingBetweenExportAttributes'
| 'unexpectedExportAttributesOrder'

let defaultOptions: Required<Options[0]> = {
fallbackSort: { type: 'unsorted' },
specialCharacters: 'keep',
partitionByComment: false,
partitionByNewLine: false,
newlinesBetween: 'ignore',
type: 'alphabetical',
ignoreCase: true,
customGroups: [],
locales: 'en-US',
alphabet: '',
order: 'asc',
groups: [],
}

export default createEslintRule<Options, MessageId>({
create: context => ({
ExportNamedDeclaration: node => {
let attributes: TSESTree.ImportAttribute[] | undefined = node.attributes
if (!isSortable(attributes)) {
return
}

let { sourceCode, id } = context
let settings = getSettings(context.settings)
let options = complete(context.options.at(0), settings, defaultOptions)
validateCustomSortConfiguration(options)
validateGeneratedGroupsConfiguration({
selectors: [],
modifiers: [],
options,
})
validateNewlinesAndPartitionConfiguration(options)

let eslintDisabledLines = getEslintDisabledLines({
ruleName: id,
sourceCode,
})

let formattedMembers: SortingNode<TSESTree.ImportAttribute>[][] = [[]]
for (let attribute of attributes) {
let name = getAttributeName(attribute, sourceCode)

let group = computeGroup({
customGroupMatcher: customGroup =>
doesCustomGroupMatch({
elementName: name,
selectors: [],
modifiers: [],
customGroup,
}),
predefinedGroups: [],
options,
})

let sortingNode: Omit<
SortingNode<TSESTree.ImportAttribute>,
'partitionId'
> = {
isEslintDisabled: isNodeEslintDisabled(
attribute,
eslintDisabledLines,
),
size: rangeToDiff(attribute, sourceCode),
node: attribute,
group,
name,
}

let lastSortingNode = formattedMembers.at(-1)?.at(-1)
if (
shouldPartition({
lastSortingNode,
sortingNode,
sourceCode,
options,
})
) {
formattedMembers.push([])
}

formattedMembers.at(-1)!.push({
...sortingNode,
partitionId: formattedMembers.length,
})
}

for (let nodes of formattedMembers) {
function createSortNodesExcludingEslintDisabled(
sortingNodes: SortingNode<TSESTree.ImportAttribute>[],
) {
return function (
ignoreEslintDisabledNodes: boolean,
): SortingNode<TSESTree.ImportAttribute>[] {
return sortNodesByGroups({
getOptionsByGroupIndex:
buildGetCustomGroupOverriddenOptionsFunction(options),
ignoreEslintDisabledNodes,
groups: options.groups,
nodes: sortingNodes,
})
}
}

reportAllErrors<MessageId>({
availableMessageIds: {
missedSpacingBetweenMembers: 'missedSpacingBetweenExportAttributes',
extraSpacingBetweenMembers: 'extraSpacingBetweenExportAttributes',
unexpectedGroupOrder: 'unexpectedExportAttributesGroupOrder',
unexpectedOrder: 'unexpectedExportAttributesOrder',
},
sortNodesExcludingEslintDisabled:
createSortNodesExcludingEslintDisabled(nodes),
sourceCode,
options,
context,
nodes,
})
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Hook up newline distance calculator

Spacing/newline diagnostics never fire because reportAllErrors receives no newlinesBetweenValueGetter. Provide it (and import getLinesBetween) so the rule can emit the promised spacing errors.

@@
-import { sortNodesByGroups } from '../utils/sort-nodes-by-groups'
+import { sortNodesByGroups } from '../utils/sort-nodes-by-groups'
+import { getLinesBetween } from '../utils/get-lines-between'
@@
         reportAllErrors<MessageId>({
           availableMessageIds: {
             missedSpacingBetweenMembers: 'missedSpacingBetweenExportAttributes',
             extraSpacingBetweenMembers: 'extraSpacingBetweenExportAttributes',
             unexpectedGroupOrder: 'unexpectedExportAttributesGroupOrder',
             unexpectedOrder: 'unexpectedExportAttributesOrder',
           },
           sortNodesExcludingEslintDisabled:
             createSortNodesExcludingEslintDisabled(nodes),
           sourceCode,
           options,
           context,
-          nodes,
+          nodes,
+          newlinesBetweenValueGetter: (left, right) =>
+            getLinesBetween(sourceCode, left, right),
         })
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
import {
buildCustomGroupsArrayJsonSchema,
partitionByCommentJsonSchema,
partitionByNewLineJsonSchema,
newlinesBetweenJsonSchema,
commonJsonSchemas,
groupsJsonSchema,
} from '../utils/common-json-schemas'
import {
MISSED_SPACING_ERROR,
EXTRA_SPACING_ERROR,
GROUP_ORDER_ERROR,
ORDER_ERROR,
} from '../utils/report-errors'
import { validateNewlinesAndPartitionConfiguration } from '../utils/validate-newlines-and-partition-configuration'
import { buildGetCustomGroupOverriddenOptionsFunction } from '../utils/get-custom-groups-compare-options'
import { validateGeneratedGroupsConfiguration } from '../utils/validate-generated-groups-configuration'
import { validateCustomSortConfiguration } from '../utils/validate-custom-sort-configuration'
import { singleCustomGroupJsonSchema } from './sort-export-attributes/types'
import { getEslintDisabledLines } from '../utils/get-eslint-disabled-lines'
import { isNodeEslintDisabled } from '../utils/is-node-eslint-disabled'
import { doesCustomGroupMatch } from '../utils/does-custom-group-match'
import { sortNodesByGroups } from '../utils/sort-nodes-by-groups'
import { createEslintRule } from '../utils/create-eslint-rule'
import { reportAllErrors } from '../utils/report-all-errors'
import { shouldPartition } from '../utils/should-partition'
import { computeGroup } from '../utils/compute-group'
import { rangeToDiff } from '../utils/range-to-diff'
import { getSettings } from '../utils/get-settings'
import { isSortable } from '../utils/is-sortable'
import { complete } from '../utils/complete'
type MessageId =
| 'missedSpacingBetweenExportAttributes'
| 'unexpectedExportAttributesGroupOrder'
| 'extraSpacingBetweenExportAttributes'
| 'unexpectedExportAttributesOrder'
let defaultOptions: Required<Options[0]> = {
fallbackSort: { type: 'unsorted' },
specialCharacters: 'keep',
partitionByComment: false,
partitionByNewLine: false,
newlinesBetween: 'ignore',
type: 'alphabetical',
ignoreCase: true,
customGroups: [],
locales: 'en-US',
alphabet: '',
order: 'asc',
groups: [],
}
export default createEslintRule<Options, MessageId>({
create: context => ({
ExportNamedDeclaration: node => {
let attributes: TSESTree.ImportAttribute[] | undefined = node.attributes
if (!isSortable(attributes)) {
return
}
let { sourceCode, id } = context
let settings = getSettings(context.settings)
let options = complete(context.options.at(0), settings, defaultOptions)
validateCustomSortConfiguration(options)
validateGeneratedGroupsConfiguration({
selectors: [],
modifiers: [],
options,
})
validateNewlinesAndPartitionConfiguration(options)
let eslintDisabledLines = getEslintDisabledLines({
ruleName: id,
sourceCode,
})
let formattedMembers: SortingNode<TSESTree.ImportAttribute>[][] = [[]]
for (let attribute of attributes) {
let name = getAttributeName(attribute, sourceCode)
let group = computeGroup({
customGroupMatcher: customGroup =>
doesCustomGroupMatch({
elementName: name,
selectors: [],
modifiers: [],
customGroup,
}),
predefinedGroups: [],
options,
})
let sortingNode: Omit<
SortingNode<TSESTree.ImportAttribute>,
'partitionId'
> = {
isEslintDisabled: isNodeEslintDisabled(
attribute,
eslintDisabledLines,
),
size: rangeToDiff(attribute, sourceCode),
node: attribute,
group,
name,
}
let lastSortingNode = formattedMembers.at(-1)?.at(-1)
if (
shouldPartition({
lastSortingNode,
sortingNode,
sourceCode,
options,
})
) {
formattedMembers.push([])
}
formattedMembers.at(-1)!.push({
...sortingNode,
partitionId: formattedMembers.length,
})
}
for (let nodes of formattedMembers) {
function createSortNodesExcludingEslintDisabled(
sortingNodes: SortingNode<TSESTree.ImportAttribute>[],
) {
return function (
ignoreEslintDisabledNodes: boolean,
): SortingNode<TSESTree.ImportAttribute>[] {
return sortNodesByGroups({
getOptionsByGroupIndex:
buildGetCustomGroupOverriddenOptionsFunction(options),
ignoreEslintDisabledNodes,
groups: options.groups,
nodes: sortingNodes,
})
}
}
reportAllErrors<MessageId>({
availableMessageIds: {
missedSpacingBetweenMembers: 'missedSpacingBetweenExportAttributes',
extraSpacingBetweenMembers: 'extraSpacingBetweenExportAttributes',
unexpectedGroupOrder: 'unexpectedExportAttributesGroupOrder',
unexpectedOrder: 'unexpectedExportAttributesOrder',
},
sortNodesExcludingEslintDisabled:
createSortNodesExcludingEslintDisabled(nodes),
sourceCode,
options,
context,
nodes,
})
// Add alongside the existing import of sortNodesByGroups
import { sortNodesByGroups } from '../utils/sort-nodes-by-groups'
import { getLinesBetween } from '../utils/get-lines-between'
// Inside the loop, update the call to reportAllErrors to pass the new helper:
reportAllErrors<MessageId>({
availableMessageIds: {
missedSpacingBetweenMembers: 'missedSpacingBetweenExportAttributes',
extraSpacingBetweenMembers: 'extraSpacingBetweenExportAttributes',
unexpectedGroupOrder: 'unexpectedExportAttributesGroupOrder',
unexpectedOrder: 'unexpectedExportAttributesOrder',
},
sortNodesExcludingEslintDisabled:
createSortNodesExcludingEslintDisabled(nodes),
sourceCode,
options,
context,
nodes,
newlinesBetweenValueGetter: (left, right) =>
getLinesBetween(sourceCode, left, right),
})
🤖 Prompt for AI Agents
In rules/sort-export-attributes.ts around lines 7 to 162, the rule never
supplies a newlinesBetweenValueGetter so spacing/newline diagnostics never fire;
import getLinesBetween from '../utils/get-lines-between' at the top of the file
and pass newlinesBetweenValueGetter: getLinesBetween in the reportAllErrors call
where the options, sourceCode, context, and nodes are passed so the rule can
compute newline distances and emit spacing errors.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
rules/sort-heritage-clauses.ts (1)

135-176: Partition IDs are incorrect.

Line 158 hardcodes partitionId: 0 for all nodes, but the 2D structure suggests each partition should have unique IDs. Update the assignment to reflect the actual partition index.

Apply this diff:

     let sortingNode: SortingNode = {
       isEslintDisabled: isNodeEslintDisabled(
         heritageClause,
         eslintDisabledLines,
       ),
       size: rangeToDiff(heritageClause, sourceCode),
       node: heritageClause,
-      partitionId: 0,
+      partitionId: formattedMembers.length,
       group,
       name,
     }
♻️ Duplicate comments (11)
rules/sort-import-attributes.ts (1)

149-162: Missing newlinesBetweenValueGetter parameter.

The reportAllErrors call is still missing the newlinesBetweenValueGetter parameter, which prevents spacing diagnostics from working correctly. This was flagged in a previous review.

Apply this diff to add the missing parameter:

+import { getLinesBetween } from '../utils/get-lines-between'
+
 // ... in the reportAllErrors call:
         reportAllErrors<MessageId>({
           availableMessageIds: {
             missedSpacingBetweenMembers: 'missedSpacingBetweenImportAttributes',
             extraSpacingBetweenMembers: 'extraSpacingBetweenImportAttributes',
             unexpectedGroupOrder: 'unexpectedImportAttributesGroupOrder',
             unexpectedOrder: 'unexpectedImportAttributesOrder',
           },
+          newlinesBetweenValueGetter: (left, right) =>
+            getLinesBetween(sourceCode, left, right),
           sortNodesExcludingEslintDisabled:
             createSortNodesExcludingEslintDisabled(nodes),
           sourceCode,
           options,
           context,
           nodes,
         })
rules/sort-export-attributes.ts (1)

7-162: Hook up newline distance calculator

Spacing/newline diagnostics never fire because reportAllErrors receives no newlinesBetweenValueGetter. Provide it (and import getLinesBetween) so the rule can emit the promised spacing errors.

Apply this diff to import getLinesBetween at the top of the file:

 import {
   buildCustomGroupsArrayJsonSchema,
   partitionByCommentJsonSchema,
   partitionByNewLineJsonSchema,
   newlinesBetweenJsonSchema,
   commonJsonSchemas,
   groupsJsonSchema,
 } from '../utils/common-json-schemas'
+import { getLinesBetween } from '../utils/get-lines-between'

Then apply this diff to pass newlinesBetweenValueGetter in the reportAllErrors call:

         reportAllErrors<MessageId>({
           availableMessageIds: {
             missedSpacingBetweenMembers: 'missedSpacingBetweenExportAttributes',
             extraSpacingBetweenMembers: 'extraSpacingBetweenExportAttributes',
             unexpectedGroupOrder: 'unexpectedExportAttributesGroupOrder',
             unexpectedOrder: 'unexpectedExportAttributesOrder',
           },
           sortNodesExcludingEslintDisabled:
             createSortNodesExcludingEslintDisabled(nodes),
           sourceCode,
           options,
           context,
           nodes,
+          newlinesBetweenValueGetter: (left, right) =>
+            getLinesBetween(sourceCode, left, right),
         })
rules/sort-array-includes.ts (2)

246-257: Verify unknown group handling to prevent unintended reordering.

Per a previous review comment, nodes with selectors not present in configured groups (e.g., 'spread') may be reordered unintentionally. Consider passing isNodeIgnored to sortNodesByGroups to keep unlisted selectors stable:

isNodeIgnored: node =>
  getGroupIndex(options.groups, node) === options.groups.length,

This ensures that spreads and other unconfigured selectors remain in their original positions by default.

Run the following script to check if spreads are handled correctly in tests:

#!/bin/bash
# Search for test cases involving spread elements
rg -n --type=ts -A5 -B5 'SpreadElement|\.\.\..*\[' test/rules/sort-array-includes.test.ts

260-268: Enable spacing diagnostics by passing newlinesBetweenValueGetter.

Per a previous review comment, the newlinesBetweenValueGetter parameter is missing, which would cause spacing-related test assertions to fail. Add:

+import { getLinesBetween } from '../utils/get-lines-between'
 
   let nodes = formattedMembers.flat()
   reportAllErrors<MessageIds>({
+    newlinesBetweenValueGetter: (left, right) =>
+      getLinesBetween(sourceCode, left, right),
     sortNodesExcludingEslintDisabled,
     availableMessageIds,
     sourceCode,
     options,
     context,
     nodes,
   })

Verify that spacing tests are passing:

#!/bin/bash
# Run tests for sort-array-includes
npm test -- sort-array-includes
rules/sort-objects.ts (2)

553-594: Address type safety: don't conflate Property with VariableDeclarator.

The return type declares type: 'VariableDeclarator' but the node field can be either TSESTree.VariableDeclarator | TSESTree.Property (line 563). This makes declarationMatchesPattern matching fire incorrectly for nested object literals, as noted in a previous review.

Separate the union so Property parents have their own discriminant:

 function getObjectParent({
   onlyFirstParent,
   sourceCode,
   node,
 }: {
   node: TSESTree.ObjectExpression | TSESTree.ObjectPattern
   sourceCode: TSESLint.SourceCode
   onlyFirstParent: boolean
 }):
   | {
-      node: TSESTree.VariableDeclarator | TSESTree.Property
+      node: TSESTree.VariableDeclarator
       type: 'VariableDeclarator'
       name: string | null
     }
+  | {
+      node: TSESTree.Property
+      type: 'Property'
+      name: string | null
+    }
   | {
       node: TSESTree.CallExpression
       type: 'CallExpression'
       name: string | null
     }
   | null {
   let variableParent = getVariableParent({ onlyFirstParent, node })
   if (variableParent) {
-    return {
-      type: 'VariableDeclarator',
-      name: variableParent.name,
-      node: variableParent.node,
-    }
+    if (
+      variableParent.node.type === TSESTree.AST_NODE_TYPES.VariableDeclarator
+    ) {
+      return {
+        type: 'VariableDeclarator',
+        name: variableParent.name,
+        node: variableParent.node,
+      }
+    }
+    return {
+      type: 'Property',
+      name: variableParent.name,
+      node: variableParent.node,
+    }
   }

Then update computeMatchedContextOptions to check objectParent.type === 'VariableDeclarator' rather than !== 'CallExpression'.


586-592: Normalize callee text to reduce false positives in callingFunctionNamePattern matching.

Using sourceCode.getText(callParent.callee) can return arbitrary wrapped expressions (e.g., (0, foo.bar)). Extract a stable identifier name instead:

function getCalleeName(expr: TSESTree.Expression): string | null {
  if (expr.type === 'Identifier') return expr.name
  if (
    expr.type === 'MemberExpression' &&
    !expr.computed &&
    expr.property.type === 'Identifier'
  ) {
    return expr.property.name // or `${obj}.${prop}` if desired
  }
  return null
}

Then use:

   if (callParent) {
+    let calleeName = getCalleeName(callParent.callee) ?? sourceCode.getText(callParent.callee)
     return {
-      name: sourceCode.getText(callParent.callee),
+      name: calleeName,
       type: 'CallExpression',
       node: callParent,
     }
   }
rules/sort-jsx-props.ts (1)

189-202: Enable spacing diagnostics (missed/extra blank lines).

Per previous review feedback, pass newlinesBetweenValueGetter so reportAllErrors can evaluate newlinesBetween for JSX props.

Apply this diff:

+import { getLinesBetween } from '../utils/get-lines-between'
@@
       reportAllErrors<MessageId>({
         availableMessageIds: {
           missedSpacingBetweenMembers: 'missedSpacingBetweenJSXPropsMembers',
           extraSpacingBetweenMembers: 'extraSpacingBetweenJSXPropsMembers',
           unexpectedGroupOrder: 'unexpectedJSXPropsGroupOrder',
           unexpectedOrder: 'unexpectedJSXPropsOrder',
         },
+        newlinesBetweenValueGetter: (left, right) =>
+          getLinesBetween(sourceCode, left, right),
         sortNodesExcludingEslintDisabled:
           createSortNodesExcludingEslintDisabled(currentNodes),
         nodes: currentNodes,
         sourceCode,
         options,
         context,
       })
rules/sort-heritage-clauses.ts (1)

193-206: Provide newlinesBetweenValueGetter to report spacing errors.

Per previous review feedback, pass newlinesBetweenValueGetter so reportAllErrors can compute missed/extra blank-line errors.

Apply this diff:

+import { getLinesBetween } from '../utils/get-lines-between'
@@
   reportAllErrors<MessageId>({
     availableMessageIds: {
       missedSpacingBetweenMembers: 'missedSpacingBetweenHeritageClauses',
       extraSpacingBetweenMembers: 'extraSpacingBetweenHeritageClauses',
       unexpectedGroupOrder: 'unexpectedHeritageClausesGroupOrder',
       unexpectedOrder: 'unexpectedHeritageClausesOrder',
     },
+    newlinesBetweenValueGetter: (left, right) =>
+      getLinesBetween(sourceCode, left, right),
     sortNodesExcludingEslintDisabled:
       createSortNodesExcludingEslintDisabled(nodes),
     sourceCode,
     options,
     context,
     nodes,
   })
rules/sort-object-types.ts (3)

329-337: Pass newlinesBetweenValueGetter to enable spacing diagnostics.

Per previous review feedback, pass newlinesBetweenValueGetter so reportAllErrors can compute missed/extra blank-line errors when options.newlinesBetween is set.

Apply this diff:

+import { getLinesBetween } from '../utils/get-lines-between'
@@
   reportAllErrors<MessageIds>({
     sortNodesExcludingEslintDisabled,
+    newlinesBetweenValueGetter: (left, right) =>
+      getLinesBetween(sourceCode, left, right),
     availableMessageIds,
     sourceCode,
     options,
     context,
     nodes,
   })

115-130: Add TSInterfaceBody visitor to include interfaces.

Per previous review feedback, add a TSInterfaceBody visitor that calls sortObjectTypeElements with parentNode set when node.parent.type === 'TSInterfaceDeclaration' and elements: node.body.

Apply this diff:

 export default createEslintRule<Options, MessageId>({
   create: context => ({
     TSTypeLiteral: node =>
       sortObjectTypeElements<MessageId>({
         availableMessageIds: {
           missedSpacingBetweenMembers: 'missedSpacingBetweenObjectTypeMembers',
           extraSpacingBetweenMembers: 'extraSpacingBetweenObjectTypeMembers',
           unexpectedGroupOrder: 'unexpectedObjectTypesGroupOrder',
           unexpectedOrder: 'unexpectedObjectTypesOrder',
         },
         parentNode:
           node.parent.type === 'TSTypeAliasDeclaration' ? node.parent : null,
         elements: node.members,
         context,
       }),
+    TSInterfaceBody: node =>
+      sortObjectTypeElements<MessageId>({
+        availableMessageIds: {
+          missedSpacingBetweenMembers: 'missedSpacingBetweenObjectTypeMembers',
+          extraSpacingBetweenMembers: 'extraSpacingBetweenObjectTypeMembers',
+          unexpectedGroupOrder: 'unexpectedObjectTypesGroupOrder',
+          unexpectedOrder: 'unexpectedObjectTypesOrder',
+        },
+        parentNode:
+          node.parent && node.parent.type === 'TSInterfaceDeclaration'
+            ? node.parent
+            : null,
+        elements: node.body,
+        context,
+      }),
   }),

235-239: Don't assign optional/required modifiers to index signatures.

Per previous review feedback, index signatures don't support optionality; adding 'required' causes misleading predefined groups.

Apply this diff:

-    if (isMemberOptional(typeElement)) {
-      modifiers.push('optional')
-    } else {
-      modifiers.push('required')
-    }
+    if (typeElement.type !== 'TSIndexSignature') {
+      if (isMemberOptional(typeElement)) {
+        modifiers.push('optional')
+      } else {
+        modifiers.push('required')
+      }
+    }
🧹 Nitpick comments (1)
rules/sort-export-attributes.ts (1)

204-213: LGTM with a minor observation

The helper correctly extracts attribute names. The fallback to sourceCode.getText(attribute) is defensive and safe.

For slightly better type safety, consider extracting the literal value directly when key.type === 'Literal':

 function getAttributeName(
   attribute: TSESTree.ImportAttribute,
   sourceCode: TSESLint.SourceCode,
 ): string {
   let { key } = attribute
   if (key.type === 'Identifier') {
     return key.name
   }
-  return key.value?.toString() ?? sourceCode.getText(attribute)
+  if (key.type === 'Literal' && typeof key.value === 'string') {
+    return key.value
+  }
+  return sourceCode.getText(attribute)
 }

This avoids calling toString() on non-string literal values and more clearly handles the expected string case.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8c3bcb5 and 30183b1.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml, !pnpm-lock.yaml
📒 Files selected for processing (24)
  • eslint.config.ts (1 hunks)
  • package.json (4 hunks)
  • rules/sort-array-includes.ts (6 hunks)
  • rules/sort-classes.ts (2 hunks)
  • rules/sort-decorators.ts (6 hunks)
  • rules/sort-enums.ts (6 hunks)
  • rules/sort-export-attributes.ts (1 hunks)
  • rules/sort-exports.ts (3 hunks)
  • rules/sort-heritage-clauses.ts (6 hunks)
  • rules/sort-import-attributes.ts (1 hunks)
  • rules/sort-imports.ts (7 hunks)
  • rules/sort-interfaces.ts (2 hunks)
  • rules/sort-intersection-types.ts (2 hunks)
  • rules/sort-jsx-props.ts (6 hunks)
  • rules/sort-maps.ts (4 hunks)
  • rules/sort-modules.ts (3 hunks)
  • rules/sort-named-exports.ts (3 hunks)
  • rules/sort-named-imports.ts (3 hunks)
  • rules/sort-object-types.ts (10 hunks)
  • rules/sort-objects.ts (11 hunks)
  • rules/sort-sets.ts (1 hunks)
  • rules/sort-switch-case.ts (3 hunks)
  • rules/sort-union-types.ts (2 hunks)
  • rules/sort-variable-declarations.ts (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (5)
  • rules/sort-classes.ts
  • package.json
  • rules/sort-enums.ts
  • rules/sort-union-types.ts
  • rules/sort-modules.ts
🧰 Additional context used
🧬 Code graph analysis (18)
rules/sort-intersection-types.ts (3)
rules/sort-array-includes.ts (1)
  • defaultOptions (60-74)
rules/sort-object-types/types.ts (1)
  • Options (28-106)
rules/sort-union-types/types.ts (1)
  • Options (22-54)
rules/sort-variable-declarations.ts (2)
rules/sort-array-includes.ts (1)
  • defaultOptions (60-74)
rules/sort-variable-declarations/types.ts (1)
  • Options (23-55)
rules/sort-exports.ts (6)
types/sorting-node.ts (1)
  • SortingNode (18-102)
rules/sort-array-includes.ts (1)
  • defaultOptions (60-74)
rules/sort-exports/types.ts (1)
  • Options (25-57)
utils/sort-nodes-by-groups.ts (1)
  • sortNodesByGroups (106-162)
utils/get-custom-groups-compare-options.ts (1)
  • buildGetCustomGroupOverriddenOptionsFunction (137-148)
utils/report-all-errors.ts (1)
  • reportAllErrors (203-325)
rules/sort-sets.ts (1)
rules/sort-array-includes.ts (1)
  • defaultOptions (60-74)
rules/sort-named-imports.ts (4)
rules/sort-named-imports/types.ts (1)
  • Options (26-66)
utils/sort-nodes-by-groups.ts (1)
  • sortNodesByGroups (106-162)
utils/get-custom-groups-compare-options.ts (1)
  • buildGetCustomGroupOverriddenOptionsFunction (137-148)
utils/report-all-errors.ts (1)
  • reportAllErrors (203-325)
rules/sort-maps.ts (3)
rules/sort-array-includes.ts (1)
  • defaultOptions (60-74)
rules/sort-maps/types.ts (1)
  • Options (20-64)
utils/filter-options-by-all-names-match.ts (1)
  • filterOptionsByAllNamesMatch (80-94)
rules/sort-switch-case.ts (1)
rules/sort-array-includes.ts (1)
  • defaultOptions (60-74)
rules/sort-interfaces.ts (2)
rules/sort-array-includes.ts (1)
  • defaultOptions (60-74)
rules/sort-object-types.ts (1)
  • sortObjectTypeElements (152-338)
rules/sort-named-exports.ts (5)
rules/sort-array-includes.ts (1)
  • defaultOptions (60-74)
rules/sort-named-exports/types.ts (1)
  • Options (26-66)
utils/sort-nodes-by-groups.ts (1)
  • sortNodesByGroups (106-162)
utils/get-custom-groups-compare-options.ts (1)
  • buildGetCustomGroupOverriddenOptionsFunction (137-148)
utils/report-all-errors.ts (1)
  • reportAllErrors (203-325)
rules/sort-imports.ts (5)
rules/sort-imports/types.ts (3)
  • Options (29-141)
  • Selector (147-167)
  • Modifier (212-220)
utils/common-json-schemas.ts (1)
  • buildCustomGroupsArrayJsonSchema (302-351)
utils/generate-predefined-groups.ts (1)
  • generatePredefinedGroups (23-56)
utils/compute-group.ts (1)
  • computeGroup (75-113)
utils/does-custom-group-match.ts (1)
  • doesCustomGroupMatch (121-141)
rules/sort-array-includes.ts (6)
types/sorting-node.ts (1)
  • SortingNode (18-102)
rules/sort-array-includes/types.ts (2)
  • Options (24-68)
  • Selector (100-100)
utils/filter-options-by-all-names-match.ts (1)
  • filterOptionsByAllNamesMatch (80-94)
utils/sort-nodes-by-groups.ts (1)
  • sortNodesByGroups (106-162)
utils/get-custom-groups-compare-options.ts (1)
  • buildGetCustomGroupOverriddenOptionsFunction (137-148)
utils/report-all-errors.ts (1)
  • reportAllErrors (203-325)
rules/sort-export-attributes.ts (19)
utils/create-eslint-rule.ts (1)
  • createEslintRule (32-35)
utils/is-sortable.ts (1)
  • isSortable (7-9)
utils/get-settings.ts (1)
  • getSettings (91-136)
utils/complete.ts (1)
  • complete (30-45)
utils/validate-custom-sort-configuration.ts (1)
  • validateCustomSortConfiguration (25-35)
utils/validate-generated-groups-configuration.ts (1)
  • validateGeneratedGroupsConfiguration (74-95)
utils/validate-newlines-and-partition-configuration.ts (1)
  • validateNewlinesAndPartitionConfiguration (98-119)
utils/get-eslint-disabled-lines.ts (1)
  • getEslintDisabledLines (45-97)
types/sorting-node.ts (1)
  • SortingNode (18-102)
utils/compute-group.ts (1)
  • computeGroup (75-113)
utils/does-custom-group-match.ts (1)
  • doesCustomGroupMatch (121-141)
utils/is-node-eslint-disabled.ts (1)
  • isNodeEslintDisabled (27-32)
utils/range-to-diff.ts (1)
  • rangeToDiff (32-41)
utils/should-partition.ts (1)
  • shouldPartition (69-95)
utils/sort-nodes-by-groups.ts (1)
  • sortNodesByGroups (106-162)
utils/get-custom-groups-compare-options.ts (1)
  • buildGetCustomGroupOverriddenOptionsFunction (137-148)
utils/report-all-errors.ts (1)
  • reportAllErrors (203-325)
utils/common-json-schemas.ts (5)
  • buildCustomGroupsArrayJsonSchema (302-351)
  • partitionByCommentJsonSchema (241-262)
  • partitionByNewLineJsonSchema (268-272)
  • newlinesBetweenJsonSchema (146-158)
  • groupsJsonSchema (165-190)
utils/report-errors.ts (4)
  • MISSED_SPACING_ERROR (33-34)
  • EXTRA_SPACING_ERROR (30-31)
  • GROUP_ORDER_ERROR (27-28)
  • ORDER_ERROR (21-22)
rules/sort-objects.ts (6)
rules/sort-objects/types.ts (1)
  • Options (25-120)
utils/common-json-schemas.ts (1)
  • regexJsonSchema (219-228)
utils/filter-options-by-all-names-match.ts (1)
  • filterOptionsByAllNamesMatch (80-94)
utils/filter-options-by-declaration-comment-matches.ts (1)
  • filterOptionsByDeclarationCommentMatches (14-39)
utils/matches.ts (1)
  • matches (39-60)
rules/sort-objects/get-first-node-parent-with-type.ts (1)
  • getFirstNodeParentWithType (21-46)
rules/sort-import-attributes.ts (19)
utils/create-eslint-rule.ts (1)
  • createEslintRule (32-35)
utils/is-sortable.ts (1)
  • isSortable (7-9)
utils/get-settings.ts (1)
  • getSettings (91-136)
utils/complete.ts (1)
  • complete (30-45)
utils/validate-custom-sort-configuration.ts (1)
  • validateCustomSortConfiguration (25-35)
utils/validate-generated-groups-configuration.ts (1)
  • validateGeneratedGroupsConfiguration (74-95)
utils/validate-newlines-and-partition-configuration.ts (1)
  • validateNewlinesAndPartitionConfiguration (98-119)
utils/get-eslint-disabled-lines.ts (1)
  • getEslintDisabledLines (45-97)
types/sorting-node.ts (1)
  • SortingNode (18-102)
utils/compute-group.ts (1)
  • computeGroup (75-113)
utils/does-custom-group-match.ts (1)
  • doesCustomGroupMatch (121-141)
utils/is-node-eslint-disabled.ts (1)
  • isNodeEslintDisabled (27-32)
utils/range-to-diff.ts (1)
  • rangeToDiff (32-41)
utils/should-partition.ts (1)
  • shouldPartition (69-95)
utils/sort-nodes-by-groups.ts (1)
  • sortNodesByGroups (106-162)
utils/get-custom-groups-compare-options.ts (1)
  • buildGetCustomGroupOverriddenOptionsFunction (137-148)
utils/report-all-errors.ts (1)
  • reportAllErrors (203-325)
utils/common-json-schemas.ts (5)
  • buildCustomGroupsArrayJsonSchema (302-351)
  • partitionByCommentJsonSchema (241-262)
  • partitionByNewLineJsonSchema (268-272)
  • newlinesBetweenJsonSchema (146-158)
  • groupsJsonSchema (165-190)
utils/report-errors.ts (4)
  • MISSED_SPACING_ERROR (33-34)
  • EXTRA_SPACING_ERROR (30-31)
  • GROUP_ORDER_ERROR (27-28)
  • ORDER_ERROR (21-22)
rules/sort-heritage-clauses.ts (10)
rules/sort-heritage-clauses/types.ts (1)
  • Options (14-22)
utils/common-json-schemas.ts (4)
  • buildCustomGroupsArrayJsonSchema (302-351)
  • partitionByNewLineJsonSchema (268-272)
  • partitionByCommentJsonSchema (241-262)
  • newlinesBetweenJsonSchema (146-158)
utils/report-errors.ts (4)
  • MISSED_SPACING_ERROR (33-34)
  • EXTRA_SPACING_ERROR (30-31)
  • GROUP_ORDER_ERROR (27-28)
  • ORDER_ERROR (21-22)
utils/validate-newlines-and-partition-configuration.ts (1)
  • validateNewlinesAndPartitionConfiguration (98-119)
types/sorting-node.ts (1)
  • SortingNode (18-102)
utils/does-custom-group-match.ts (1)
  • doesCustomGroupMatch (121-141)
utils/should-partition.ts (1)
  • shouldPartition (69-95)
utils/sort-nodes-by-groups.ts (1)
  • sortNodesByGroups (106-162)
utils/get-custom-groups-compare-options.ts (1)
  • buildGetCustomGroupOverriddenOptionsFunction (137-148)
utils/report-all-errors.ts (1)
  • reportAllErrors (203-325)
rules/sort-decorators.ts (7)
rules/sort-decorators/types.ts (1)
  • Options (16-29)
utils/common-json-schemas.ts (4)
  • buildCustomGroupsArrayJsonSchema (302-351)
  • partitionByNewLineJsonSchema (268-272)
  • newlinesBetweenJsonSchema (146-158)
  • groupsJsonSchema (165-190)
utils/report-errors.ts (4)
  • MISSED_SPACING_ERROR (33-34)
  • EXTRA_SPACING_ERROR (30-31)
  • GROUP_ORDER_ERROR (27-28)
  • ORDER_ERROR (21-22)
utils/validate-generated-groups-configuration.ts (1)
  • validateGeneratedGroupsConfiguration (74-95)
utils/validate-newlines-and-partition-configuration.ts (1)
  • validateNewlinesAndPartitionConfiguration (98-119)
utils/does-custom-group-match.ts (1)
  • doesCustomGroupMatch (121-141)
utils/get-custom-groups-compare-options.ts (1)
  • buildGetCustomGroupOverriddenOptionsFunction (137-148)
rules/sort-object-types.ts (4)
rules/sort-object-types/types.ts (1)
  • Options (28-106)
utils/filter-options-by-all-names-match.ts (1)
  • filterOptionsByAllNamesMatch (80-94)
utils/filter-options-by-declaration-comment-matches.ts (1)
  • filterOptionsByDeclarationCommentMatches (14-39)
utils/matches.ts (1)
  • matches (39-60)
rules/sort-jsx-props.ts (4)
rules/sort-jsx-props/types.ts (1)
  • Options (24-65)
utils/common-json-schemas.ts (1)
  • buildCustomGroupsArrayJsonSchema (302-351)
utils/filter-options-by-all-names-match.ts (1)
  • filterOptionsByAllNamesMatch (80-94)
utils/matches.ts (1)
  • matches (39-60)
🔇 Additional comments (46)
rules/sort-sets.ts (1)

59-59: No changes needed for defaultOptions duplication
The placement of defaultOptions in both the meta object and at the top level aligns with the established pattern across other rules and the createEslintRule helper signature.

rules/sort-intersection-types.ts (2)

20-20: LGTM: Typing refinement aligns with array-based options standard.

The change from Options[0] to Options[number] correctly represents that defaultOptions should match any element of the Options array type, not just the first element. This is consistent with similar changes across other rules in this PR.


48-48: LGTM: Public exposure of defaultOptions via metadata.

Adding defaultOptions to the rule's meta object makes the default configuration publicly accessible through ESLint's metadata API, which is consistent with the standardization effort across all rules in this PR.

rules/sort-import-attributes.ts (5)

1-43: LGTM!

The imports are well-organized, and the MessageId type definition correctly captures all four error scenarios for the rule (spacing, group order, and attribute order).


45-58: LGTM!

The default options are correctly typed and include all standard configuration fields consistent with other sorting rules in the plugin.


60-130: LGTM!

The rule correctly:

  • Guards against non-sortable attributes using isSortable
  • Validates all configuration aspects (custom sort, groups, newlines/partitioning)
  • Computes groups using the standard computeGroup utility
  • Implements partitioning logic consistent with other rules in the plugin

166-202: LGTM!

The rule metadata is well-structured:

  • Schema correctly uses common JSON schemas for consistency
  • Messages use standard error constants
  • Documentation URL and description are appropriate
  • recommended: true is suitable for a new sorting rule
  • Default options are properly declared

204-213: LGTM!

The getAttributeName helper correctly handles both Identifier and Literal key types, with defensive fallback to the full source text.

rules/sort-maps.ts (4)

25-25: LGTM! Import aligns with the refactored utility.

The import change from getMatchingContextOptions to filterOptionsByAllNamesMatch is consistent with the function call update at line 81 and reflects the broader migration to standardized context-matching utilities across rules.


46-46: LGTM! Type change improves consistency.

The change from Required<Options[0]> to Required<Options[number]> aligns with the pattern used across other rules (e.g., sort-array-includes.ts) and is more idiomatic for uniform array element types.


81-88: LGTM! Function call correctly uses the refactored utility.

The call to filterOptionsByAllNamesMatch properly provides the required parameters (nodeNames and contextOptions). The nodeNames computation correctly filters out null and SpreadElement entries before mapping to names, and the return value is used consistently with the previous implementation.


235-235: LGTM! Metadata addition improves rule introspection.

Adding defaultOptions to the rule's meta object exposes the defaults for ESLint tooling and plugins (such as eslint-plugin-eslint-plugin) to introspect, improving compatibility and discoverability.

Based on learnings

eslint.config.ts (1)

3-3: LGTM! Import path simplified correctly.

The import now references the main package export instead of a deep subpath, which aligns with accessing the config via the configs property on line 7.

rules/sort-interfaces.ts (4)

20-20: LGTM: Type annotation updated to array-based Options pattern.

The change from Required<Options[0]> to Required<Options[number]> aligns with the PR-wide migration to array-based option definitions.


29-29: LGTM: Array-based customGroups default aligns with new API.

The default customGroups: [] is consistent with the PR-wide shift from object-mapped to array-based custom group definitions.


50-50: LGTM: defaultOptions exposed in meta.

Exposing defaultOptions in the rule's metadata is consistent with the pattern applied across multiple rules in this PR.


55-67: LGTM: Handler signature updated correctly.

The TSInterfaceDeclaration handler now properly forwards parentNode, elements, and context to sortObjectTypeElements, matching the expected function signature shown in rules/sort-object-types.ts.

rules/sort-switch-case.ts (3)

30-30: LGTM: Type annotation updated to array-based Options pattern.

The change from Required<Options[0]> to Required<Options[number]> is consistent with the PR-wide migration to array-based option definitions.


213-236: LGTM: Immutable sorting with toSorted.

Replacing in-place .sort() with immutable .toSorted() eliminates potential mutation bugs. This is safe given the PR's Node.js ≥20 requirement (ES2023 support).


289-289: LGTM: defaultOptions exposed in meta.

Exposing defaultOptions in the rule's metadata is consistent with the pattern applied across multiple rules in this PR.

rules/sort-variable-declarations.ts (2)

50-50: LGTM: Type annotation updated to array-based Options pattern.

The change from Required<Options[0]> to Required<Options[number]> is consistent with the PR-wide migration.


225-225: LGTM: defaultOptions exposed in meta.

Exposing defaultOptions in the rule's metadata is consistent with the pattern applied across multiple rules in this PR.

rules/sort-named-exports.ts (3)

54-68: LGTM: defaultOptions migrated to groups-based model.

The updated defaultOptions removes the deprecated groupKind field and introduces groups: [] as the default, aligning with the PR-wide migration to array-based grouping.


168-195: LGTM: Sorting flow refactored to use groups-based model.

The new sortNodesExcludingEslintDisabled function correctly delegates to sortNodesByGroups with per-group options via buildGetCustomGroupOverriddenOptionsFunction. Centralized error reporting via reportAllErrors is consistent with the pattern used in other rules (e.g., sort-named-imports, sort-exports).


232-232: LGTM: defaultOptions exposed in meta.

Exposing defaultOptions in the rule's metadata is consistent with the pattern applied across multiple rules in this PR.

rules/sort-array-includes.ts (6)

32-32: LGTM: New utility import for context matching.

The filterOptionsByAllNamesMatch import is correctly used for context-based option filtering at lines 166-171.


56-58: LGTM: Simplified to type alias without groupKind.

Changing from an interface with a groupKind field to a simple type alias aligns with the PR-wide removal of the deprecated groupKind property.


60-73: LGTM: defaultOptions migrated to groups-based model with sensible default.

The groups: ['literal'] default ensures literal elements are sorted before spreads, which is a reasonable default behavior for array includes.


136-136: LGTM: defaultOptions exposed in meta.

Exposing defaultOptions in the rule's metadata is consistent with the pattern applied across multiple rules in this PR.


166-171: LGTM: Context matching updated to use filterOptionsByAllNamesMatch.

The new context matching logic correctly filters options based on the allNamesMatchPattern configuration, consistent with the utility function's implementation.


197-198: LGTM: Selector logic simplified.

Direct determination of selector based on element type is clearer and aligns with the removal of the groupKind property.

rules/sort-named-imports.ts (3)

54-68: LGTM: defaultOptions migrated to groups-based model.

The updated defaultOptions removes the deprecated groupKind field and introduces groups: [] as the default, aligning with the PR-wide migration.


165-192: LGTM: Sorting flow refactored to use groups-based model.

The new sortNodesExcludingEslintDisabled function correctly delegates to sortNodesByGroups. This pattern is consistent with other rules in the PR. The SortNamedImportsSortingNode type issue noted in a previous review has been addressed.


229-229: LGTM: defaultOptions exposed in meta.

Exposing defaultOptions in the rule's metadata is consistent with the pattern applied across multiple rules in this PR.

rules/sort-exports.ts (4)

50-52: LGTM: Simplified to type alias without groupKind.

Changing from an interface with a groupKind field to a simple type alias aligns with the PR-wide removal of the deprecated groupKind property.


54-67: LGTM: defaultOptions migrated to groups-based model.

The updated defaultOptions removes the deprecated groupKind field and introduces array-based grouping, aligning with the PR-wide migration.


151-179: LGTM: Sorting flow refactored to use groups-based model.

The new sortNodesExcludingEslintDisabled function correctly delegates to sortNodesByGroups with per-group options. Centralized error reporting via reportAllErrors is consistent with the pattern used in other rules.


220-220: LGTM: defaultOptions exposed in meta.

Exposing defaultOptions in the rule's metadata is consistent with the pattern applied across multiple rules in this PR.

rules/sort-objects.ts (8)

27-27: LGTM: New utility imports for enhanced context matching.

The filterOptionsByDeclarationCommentMatches and filterOptionsByAllNamesMatch imports support the new declarationCommentMatchesPattern and allNamesMatchPattern configuration options in useConfigurationIf.

Also applies to: 37-37


66-84: LGTM: defaultOptions migrated to groups-based model.

The updated defaultOptions introduces array-based customGroups and adds useConfigurationIf: {}, aligning with the PR-wide migration.


98-102: LGTM: Context matching refactored to use computeMatchedContextOptions.

The new computeMatchedContextOptions function centralizes context option filtering. The function implementation will be reviewed separately.


117-119: LGTM: Simplified control flow for objectDeclarations check.

The else if structure is clearer and maintains the same logic.


425-442: LGTM: Schema updated for new configuration options.

The schema correctly exposes new useConfigurationIf properties (declarationCommentMatchesPattern, declarationMatchesPattern) and uses array-based customGroups schema.


467-467: LGTM: defaultOptions exposed in meta.

Exposing defaultOptions in the rule's metadata is consistent with the pattern applied across multiple rules in this PR.


475-551: LGTM: Centralized context matching with appropriate type guards.

The computeMatchedContextOptions function correctly:

  • Filters by allNamesMatchPattern and declarationCommentMatchesPattern
  • Guards callingFunctionNamePattern matching with objectParent.type === 'CallExpression' check (lines 521)
  • Guards declarationMatchesPattern matching with objectParent.type === 'VariableDeclarator' check (line 537)

These type guards address the concerns raised in previous reviews.


596-634: LGTM: getVariableParent correctly extracts parent information.

The function properly handles both VariableDeclarator and Property parent types, extracting the appropriate identifier name from each.

Repository owner deleted a comment from coderabbitai bot Nov 16, 2025
Repository owner deleted a comment from coderabbitai bot Nov 16, 2025
Repository owner deleted a comment from coderabbitai bot Nov 16, 2025
Repository owner deleted a comment from coderabbitai bot Nov 16, 2025
Repository owner deleted a comment from coderabbitai bot Nov 16, 2025
Repository owner deleted a comment from coderabbitai bot Nov 16, 2025
Repository owner deleted a comment from coderabbitai bot Nov 16, 2025
Repository owner deleted a comment from coderabbitai bot Nov 16, 2025
Repository owner deleted a comment from coderabbitai bot Nov 16, 2025
Repository owner deleted a comment from coderabbitai bot Nov 16, 2025
Repository owner deleted a comment from coderabbitai bot Nov 16, 2025
Repository owner deleted a comment from coderabbitai bot Nov 16, 2025
Repository owner deleted a comment from coderabbitai bot Nov 16, 2025
Repository owner deleted a comment from coderabbitai bot Nov 16, 2025
Repository owner deleted a comment from coderabbitai bot Nov 16, 2025
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (6)
docs/content/rules/sort-object-types.mdx (2)

721-721: Remove deprecated ignorePattern from defaults in Usage examples.

Docs mark ignorePattern as deprecated, but the Flat/Legacy config blocks still include it. Drop it to avoid suggesting removed APIs.

-                  ignorePattern: [],

Also applies to: 754-754


189-191: Minor wording

“Use object types keys” → “Use object type keys.”

docs/content/rules/sort-intersection-types.mdx (1)

401-401: Minor grammar

Use “A type member …” instead of “An type member …”.

Also applies to: 419-419

docs/content/rules/sort-modules.mdx (1)

276-281: Terminology: “class” → “module members”

This rule sorts module members; adjust the description in partitionByNewLine.

- When `true`, the rule will not sort the members of a class if there is an empty line between them.
+ When `true`, the rule will not sort module members if there is an empty line between them.
docs/content/rules/sort-sets.mdx (1)

296-302: Fix wording: this rule targets Set elements, not Array elements.

Minor clarity tweak.

-- `literal` — Array elements that are not spread values.
- - `spread` — Array elements that are spread values.
+- `literal` — Set elements that are not spread values.
+- `spread` — Set elements that are spread values.
docs/content/rules/sort-objects.mdx (1)

627-631: customGroups type shows old API; update to array-based definitions.

This contradicts the migration notice just above. Switch to the new array signature for consistency.

-<sub>
-  type: `{ [groupName: string]: string | string[] }`
-</sub>
+<sub>
+  type: `Array<CustomGroupDefinition | CustomGroupAnyOfDefinition>`
+</sub>
♻️ Duplicate comments (6)
docs/content/rules/sort-heritage-clauses.mdx (1)

291-298: Include 'custom' in type union and align newlinesInside typing (consistency).

Add 'custom' to the type union and consider newlinesInside?: 'always' | 'never' | number to match other docs/interfaces.

 interface CustomGroupDefinition {
   groupName: string
-  type?: 'alphabetical' | 'natural' | 'line-length' | 'unsorted'
+  type?: 'alphabetical' | 'natural' | 'line-length' | 'custom' | 'unsorted'
   order?: 'asc' | 'desc'
   fallbackSort?: { type: string; order?: 'asc' | 'desc' }
-  newlinesInside?: number
+  newlinesInside?: 'always' | 'never' | number
   elementNamePattern?: string | string[] | { pattern: string; flags?: string } | { pattern: string; flags?: string }[]
 }

 interface CustomGroupAnyOfDefinition {
   groupName: string
-  type?: 'alphabetical' | 'natural' | 'line-length' | 'unsorted'
+  type?: 'alphabetical' | 'natural' | 'line-length' | 'custom' | 'unsorted'
   order?: 'asc' | 'desc'
   fallbackSort?: { type: string; order?: 'asc' | 'desc' }
-  newlinesInside?: number
+  newlinesInside?: 'always' | 'never' | number
   anyOf: Array<{
       selector?: string
       elementNamePattern?: string | string[] | { pattern: string; flags?: string } | { pattern: string; flags?: string }[]
   }>
 }

Also applies to: 306-317

docs/content/rules/sort-modules.mdx (2)

517-522: Fix trailing dot in example (invalid TS/JSON).

Remove the dot after 'Input' in elementNamePattern.

-            elementNamePattern: 'Input'.
+            elementNamePattern: 'Input'-            elementNamePattern: 'Input'.
+            elementNamePattern: 'Input'

685-686: Update test link path

Tests live under test/rules/….

-- [Test source](https://github.com/azat-io/eslint-plugin-perfectionist/blob/main/test/sort-modules.test.ts)
+- [Test source](https://github.com/azat-io/eslint-plugin-perfectionist/blob/main/test/rules/sort-modules.test.ts)
docs/content/rules/sort-enums.mdx (1)

173-180: sortByValue default and enum values — LGTM.

Clear explanation of 'always' | 'never' | 'ifNumericEnum'.

docs/content/rules/sort-decorators.mdx (1)

368-407: Align CustomGroupDefinition / CustomGroupAnyOfDefinition typings with runtime

The examples still show:

  • fallbackSort?: { type: string; order?: 'asc' | 'desc' }
  • newlinesInside?: number

while the rest of the rule (and prior review context) indicate a more precise shape and additional literal values for newlinesInside. To avoid misleading consumers, please update both interfaces to mirror the runtime/types module, e.g.:

 interface CustomGroupDefinition {
   groupName: string
-  type?: 'alphabetical' | 'natural' | 'line-length' | 'unsorted'
+  type?: 'alphabetical' | 'natural' | 'line-length' | 'custom' | 'unsorted'
   order?: 'asc' | 'desc'
-  fallbackSort?: { type: string; order?: 'asc' | 'desc' }
-  newlinesInside?: number
+  fallbackSort?: {
+    type: 'alphabetical' | 'natural' | 'line-length' | 'custom' | 'unsorted'
+    order?: 'asc' | 'desc'
+  }
+  newlinesInside?: 'always' | 'never' | number
+  selector?: string
   elementNamePattern?: string | string[] | { pattern: string; flags?: string } | { pattern: string; flags?: string }[]
 }

and similarly for CustomGroupAnyOfDefinition’s fallbackSort and newlinesInside. Also consider expanding the newlinesInside bullet point to mention the allowed string literals explicitly.

Based on past review comments

docs/content/rules/sort-jsx-props.mdx (1)

284-286: Fix the RGB regex pattern (duplicate of prior feedback).

The regex pattern '^r|g|b$' in allNamesMatchPattern is incorrectly anchored. It parses as (^r) or g or (b$), matching unintended names like "something_g_anything" in addition to the intended "r", "g", "b". This was flagged in a prior review and remains unfixed.

Apply this fix:

      useConfigurationIf: {
-       allNamesMatchPattern: '^r|g|b$',
+       allNamesMatchPattern: '^(?:r|g|b)$',
      },
🧹 Nitpick comments (29)
docs/content/rules/sort-classes.mdx (1)

738-783: Complex customGroups example may benefit from additional guidance.

The extended example at lines 738–783 demonstrates advanced features (multiple custom groups, selector/modifier filters, anyOf patterns) but is quite dense. While comprehensive, it could be enhanced with:

  1. A simpler introductory example (e.g., single custom group) before this complex one.
  2. Step-by-step explanations within the code comments to guide users through the logic.

The example is correct and covers important patterns, but readability could be improved for users unfamiliar with the customGroups API.

Consider breaking this into a simpler introductory example followed by the current advanced example, or add inline comments explaining the matching logic (e.g., "This group matches constructor() to prevent sorting" at line 755).

test/rules/sort-classes.test.ts (5)

4129-4178: Clarify test title or remove unused boundary in groups.

The test name says: “enforces no newline … when 'newlinesBetween: 0' exists between all groups”, but the groups array also contains an unused { newlinesBetween: 1 } boundary later in the list. Since only 'a' and 'b' are present in the code, it’s harmless but confusing. Either:

  • rename the test to “…between relevant groups”, or
  • drop the trailing { newlinesBetween: 1 } (and 'c') from groups to match the title exactly.

Also applies to: 8780-8829, 13363-13412


3894-3946: Normalize fixture indentation in newline‑removal tests.

The inputs/outputs mix inconsistent leading spaces (e.g., lines for y/z). This can make tests brittle against formatting tweaks. Consider aligning indentation (or adding a comment that spacing is intentional) to keep focus on newline behavior.

Also applies to: 8544-8596, 13135-13180


3949-3952: Add “2” case to overload‑signature spacing matrix.

You already test newlinesBetween = 0, 1, and 'ignore'. Add a '2' case to ensure overload signatures still collapse adjacent lines even when the global/group setting prefers extra blank lines.

Please confirm that overloads must always be contiguous regardless of newlinesBetween (including 2). If not, we can drop this suggestion.

Also applies to: 8599-8601, 13183-13185


14691-14794: newlinesInside coverage is good; consider edge values if supported.

Nice addition of newlinesInside = 0 and 1. If the option also supports 2 (or 'ignore'), add a small matrix similar to overload tests; otherwise, a brief comment noting supported values would help readers.

Confirm the allowed domain for newlinesInside (0/1 only vs. also 2/'ignore').

Also applies to: 14828-14831, 14866-14918


4011-4019: Minor DRY: generate consecutive‑group spacing tests across strategies.

These blocks are basically identical under 'alphabetical', 'natural', and 'line‑length'. You could wrap them in describe.each(['alphabetical','natural','line-length']) with a small helper to build options to reduce duplication. Optional, readability win only.

Also applies to: 8661-8669, 13245-13253

docs/content/rules/sort-object-types.mdx (3)

322-322: Correct regex grouping in example.

'^r|g|b$' matches unintended strings. Prefer ^(?:r|g|b)$ (or ^[rgb]$) to match exactly r/g/b.

-        allNamesMatchPattern: '^r|g|b$',
+        allNamesMatchPattern: '^(?:r|g|b)$',

342-342: Fix invalid glob-like regex.

Use '.*Metadata$' (regex) instead of '*Metadata$'.

-        declarationMatchesPattern: '*Metadata$',
+        declarationMatchesPattern: '.*Metadata$',

781-782: Update test link path

Tests live under test/rules/…. Update the “Test source” link.

-- [Test source](https://github.com/azat-io/eslint-plugin-perfectionist/blob/main/test/sort-object-types.test.ts)
+- [Test source](https://github.com/azat-io/eslint-plugin-perfectionist/blob/main/test/rules/sort-object-types.test.ts)
docs/content/rules/sort-heritage-clauses.mdx (1)

442-443: Update test link path

Point to test/rules/sort-heritage-clauses.test.ts.

-- [Test source](https://github.com/azat-io/eslint-plugin-perfectionist/blob/main/test/sort-heritage-clauses.test.ts)
+- [Test source](https://github.com/azat-io/eslint-plugin-perfectionist/blob/main/test/rules/sort-heritage-clauses.test.ts)
docs/content/rules/sort-variable-declarations.mdx (2)

297-305: Add 'custom' to type union and consider richer newlinesInside typing.

For parity with rule-level type and other pages, include 'custom'; consider newlinesInside?: 'always' | 'never' | number.

 interface CustomGroupDefinition {
   groupName: string
-  type?: 'alphabetical' | 'natural' | 'line-length' | 'unsorted'
+  type?: 'alphabetical' | 'natural' | 'line-length' | 'custom' | 'unsorted'
   order?: 'asc' | 'desc'
   fallbackSort?: { type: string; order?: 'asc' | 'desc' }
-  newlinesInside?: number
+  newlinesInside?: 'always' | 'never' | number
   selector?: string
   elementNamePattern?: string | string[] | { pattern: string; flags?: string } | { pattern: string; flags?: string }[]
 }
 …
 interface CustomGroupAnyOfDefinition {
   groupName: string
-  type?: 'alphabetical' | 'natural' | 'line-length' | 'unsorted'
+  type?: 'alphabetical' | 'natural' | 'line-length' | 'custom' | 'unsorted'
   order?: 'asc' | 'desc'
   fallbackSort?: { type: string; order?: 'asc' | 'desc' }
-  newlinesInside?: number
+  newlinesInside?: 'always' | 'never' | number
   anyOf: Array<{
       selector?: string
       elementNamePattern?: string | string[] | { pattern: string; flags?: string } | { pattern: string; flags?: string }[]
   }>
 }

Also applies to: 313-324


423-424: Update test link path

Point to test/rules/sort-variable-declarations.test.ts.

-- [Test source](https://github.com/azat-io/eslint-plugin-perfectionist/blob/main/test/sort-variable-declarations.test.ts)
+- [Test source](https://github.com/azat-io/eslint-plugin-perfectionist/blob/main/test/rules/sort-variable-declarations.test.ts)
docs/content/rules/sort-named-imports.mdx (2)

343-351: Include 'custom' in type unions and consider newlinesInside parity.

Align with top-level type and other docs.

 interface CustomGroupDefinition {
   groupName: string
-  type?: 'alphabetical' | 'natural' | 'line-length' | 'unsorted'
+  type?: 'alphabetical' | 'natural' | 'line-length' | 'custom' | 'unsorted'
   order?: 'asc' | 'desc'
   fallbackSort?: { type: string; order?: 'asc' | 'desc' }
-  newlinesInside?: number
+  newlinesInside?: 'always' | 'never' | number
   selector?: string
   elementNamePattern?: …
 }
 …
 interface CustomGroupAnyOfDefinition {
   groupName: string
-  type?: 'alphabetical' | 'natural' | 'line-length' | 'unsorted'
+  type?: 'alphabetical' | 'natural' | 'line-length' | 'custom' | 'unsorted'
   order?: 'asc' | 'desc'
   fallbackSort?: { type: string; order?: 'asc' | 'desc' }
-  newlinesInside?: number
+  newlinesInside?: 'always' | 'never' | number
   anyOf: Array<{ … }>
 }

Also applies to: 359-370


471-472: Update test link path

Point to test/rules/sort-named-imports.test.ts.

-- [Test source](https://github.com/azat-io/eslint-plugin-perfectionist/blob/main/test/sort-named-imports.test.ts)
+- [Test source](https://github.com/azat-io/eslint-plugin-perfectionist/blob/main/test/rules/sort-named-imports.test.ts)
docs/content/rules/sort-intersection-types.mdx (2)

390-398: Add 'custom' to type unions and consider newlinesInside parity.

Keep these interfaces consistent with rule-level type.

 interface CustomGroupDefinition {
   groupName: string
-  type?: 'alphabetical' | 'natural' | 'line-length' | 'unsorted'
+  type?: 'alphabetical' | 'natural' | 'line-length' | 'custom' | 'unsorted'
   order?: 'asc' | 'desc'
   fallbackSort?: { type: string; order?: 'asc' | 'desc' }
-  newlinesInside?: number
+  newlinesInside?: 'always' | 'never' | number
   selector?: string
   elementNamePattern?: …
 }
 …
 interface CustomGroupAnyOfDefinition {
   groupName: string
-  type?: 'alphabetical' | 'natural' | 'line-length' | 'unsorted'
+  type?: 'alphabetical' | 'natural' | 'line-length' | 'custom' | 'unsorted'
   order?: 'asc' | 'desc'
   fallbackSort?: { type: string; order?: 'asc' | 'desc' }
-  newlinesInside?: number
+  newlinesInside?: 'always' | 'never' | number
   anyOf: Array<{ … }>
 }

Also applies to: 406-416


516-517: Update test link path

Point to test/rules/sort-intersection-types.test.ts.

-- [Test source](https://github.com/azat-io/eslint-plugin-perfectionist/blob/main/test/sort-intersection-types.test.ts)
+- [Test source](https://github.com/azat-io/eslint-plugin-perfectionist/blob/main/test/rules/sort-intersection-types.test.ts)
docs/content/rules/sort-array-includes.mdx (2)

391-398: Add 'custom' to type unions and consider newlinesInside parity.

Align with the top-level type and other pages.

 interface CustomGroupDefinition {
   groupName: string
-  type?: 'alphabetical' | 'natural' | 'line-length' | 'unsorted'
+  type?: 'alphabetical' | 'natural' | 'line-length' | 'custom' | 'unsorted'
   order?: 'asc' | 'desc'
   fallbackSort?: { type: string; order?: 'asc' | 'desc' }
-  newlinesInside?: number
+  newlinesInside?: 'always' | 'never' | number
   selector?: string
   elementNamePattern?: …
 }
 …
 interface CustomGroupAnyOfDefinition {
   groupName: string
-  type?: 'alphabetical' | 'natural' | 'line-length' | 'unsorted'
+  type?: 'alphabetical' | 'natural' | 'line-length' | 'custom' | 'unsorted'
   order?: 'asc' | 'desc'
   fallbackSort?: { type: string; order?: 'asc' | 'desc' }
-  newlinesInside?: number
+  newlinesInside?: 'always' | 'never' | number
   anyOf: Array<{ … }>
 }

Also applies to: 406-417


516-517: Update test link path

Point to test/rules/sort-array-includes.test.ts.

-- [Test source](https://github.com/azat-io/eslint-plugin-perfectionist/blob/main/test/sort-array-includes.test.ts)
+- [Test source](https://github.com/azat-io/eslint-plugin-perfectionist/blob/main/test/rules/sort-array-includes.test.ts)
docs/content/rules/sort-maps.mdx (1)

276-287: Allow 'ignore' in per-gap newlines type (keep docs in sync with behavior).

Group-level { newlinesBetween: ... } should also accept 'ignore', not just number. Tests use 'ignore' in group descriptors elsewhere; align the public surface.

-    Array<
+    Array<
       | string
       | string[]
-      | { newlinesBetween: number }
+      | { newlinesBetween: number | 'ignore' }
       | {
           group: string | string[];
           type: 'alphabetical' | 'natural' | 'line-length' | 'custom' | 'unsorted';
         }
     >
docs/content/rules/sort-interfaces.mdx (2)

304-314: New filters look good; make flags consistently optional.

Across docs you sometimes show { pattern; flags } and elsewhere flags?. Make it consistently optional to match typical RegExp options.

-    declarationCommentMatchesPattern?: string | string[] | { pattern: string; flags: string } | { pattern: string; flags: string }[]
+    declarationCommentMatchesPattern?: string | string[] | { pattern: string; flags?: string } | { pattern: string; flags?: string }[]
-    hasNumericKeysOnly?: boolean
+    hasNumericKeysOnly?: boolean

419-433: Allow 'ignore' in per-gap newlines type inside groups.

Docs show { newlinesBetween: number }, but tests use 'ignore' at the group level. Update the union for accuracy.

-      | { newlinesBetween: number }
+      | { newlinesBetween: number | 'ignore' }
docs/content/rules/sort-sets.mdx (1)

271-285: Permit 'ignore' in per-gap newlines type inside groups.

Align group descriptor type with actual behavior (allow 'ignore' as well as numbers).

-      | { newlinesBetween: number }
+      | { newlinesBetween: number | 'ignore' }
docs/content/rules/sort-enums.mdx (1)

236-247: Allow 'ignore' for group-level newlinesBetween.

To match tests and other rules, permit 'ignore' in group descriptors.

-      | { newlinesBetween: number }
+      | { newlinesBetween: number | 'ignore' }
test/rules/sort-enums.test.ts (1)

4711-4760: Minor: newlinesBetween default examples across docs.

In some rule pages, examples still use newlinesBetween: false. Public type is number | 'ignore'. Recommend normalizing examples to 'ignore'.

docs/content/rules/sort-objects.mdx (2)

463-475: Allow 'ignore' in per-gap newlines type inside groups.

Align with behavior used in tests for other rules.

-      | { newlinesBetween: number }
+      | { newlinesBetween: number | 'ignore' }

258-272: Nit: terminate with semicolons consistently in TS examples.

Optional, but keeping ; after object literals’ properties can reduce diffs in copy-paste.

docs/content/rules/sort-exports.mdx (1)

216-229: Permit 'ignore' in per-gap newlines type inside groups.

Bring group descriptor union in line with other rules.

-      | { newlinesBetween: number }
+      | { newlinesBetween: number | 'ignore' }
test/rules/sort-array-includes.test.ts (1)

1398-1723: Combinatorial newlinesBetween tests are precise but quite verbose

The matrix of global vs inline newlinesBetween values (0, 1, 2, 'ignore') plus unused groups and different error kinds (extraSpacing, missedSpacing) is very comprehensive and matches the documented precedence rules.

If this starts to drift across rules, consider extracting shared helpers (e.g. a small generator for these option matrices) to keep maintenance manageable, but it’s optional at this point.

Also applies to: 3172-3496, 4927-5251

docs/content/rules/sort-decorators.mdx (1)

247-269: Clarify partitionByNewLine semantics

The current text (“will not sort the decorators if there is an empty line between them”) can be read as “no sorting happens at all” when any blank line exists. Consider rephrasing to something like “treats decorators separated by empty lines as independent partitions and only sorts within each partition” to match the tests.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8f2126c and 513d13e.

📒 Files selected for processing (27)
  • docs/content/rules/sort-array-includes.mdx (4 hunks)
  • docs/content/rules/sort-classes.mdx (3 hunks)
  • docs/content/rules/sort-decorators.mdx (5 hunks)
  • docs/content/rules/sort-enums.mdx (6 hunks)
  • docs/content/rules/sort-export-attributes.mdx (1 hunks)
  • docs/content/rules/sort-exports.mdx (3 hunks)
  • docs/content/rules/sort-heritage-clauses.mdx (5 hunks)
  • docs/content/rules/sort-import-attributes.mdx (1 hunks)
  • docs/content/rules/sort-imports.mdx (5 hunks)
  • docs/content/rules/sort-interfaces.mdx (7 hunks)
  • docs/content/rules/sort-intersection-types.mdx (5 hunks)
  • docs/content/rules/sort-jsx-props.mdx (7 hunks)
  • docs/content/rules/sort-maps.mdx (2 hunks)
  • docs/content/rules/sort-modules.mdx (3 hunks)
  • docs/content/rules/sort-named-exports.mdx (2 hunks)
  • docs/content/rules/sort-named-imports.mdx (2 hunks)
  • docs/content/rules/sort-object-types.mdx (7 hunks)
  • docs/content/rules/sort-objects.mdx (9 hunks)
  • docs/content/rules/sort-sets.mdx (4 hunks)
  • docs/content/rules/sort-union-types.mdx (4 hunks)
  • docs/content/rules/sort-variable-declarations.mdx (2 hunks)
  • test/rules/sort-array-includes.test.ts (41 hunks)
  • test/rules/sort-classes.test.ts (27 hunks)
  • test/rules/sort-decorators.test.ts (2 hunks)
  • test/rules/sort-enums.test.ts (41 hunks)
  • test/rules/sort-export-attributes.test.ts (1 hunks)
  • test/rules/sort-exports.test.ts (49 hunks)
✅ Files skipped from review due to trivial changes (1)
  • docs/content/rules/sort-import-attributes.mdx
🚧 Files skipped from review as they are similar to previous changes (3)
  • docs/content/rules/sort-named-exports.mdx
  • test/rules/sort-export-attributes.test.ts
  • docs/content/rules/sort-export-attributes.mdx
🔇 Additional comments (44)
docs/content/rules/sort-union-types.mdx (4)

235-246: Type definition for groups option is well-structured and clear.

The union type correctly represents the new array-based groups API with per-group overrides (newlinesBetween objects and type overrides). This aligns with the v5.0.0 API migration and is documented clearly with the nested structure.


320-320: Code fence language changes from js to ts are appropriate.

The examples in these code blocks use TypeScript syntax (e.g., groups: [...] with type-aware grouping), so the language specifier change is correct and improves syntax highlighting for readers.

Also applies to: 356-356


366-379: Per-group overrides section is clear and well-integrated.

The "Group with overridden settings" section effectively documents the new capability to override options (like type) per-group. The example is concise and directly illustrates the feature.


232-248: Consider adding a migration notice for customGroups API changes (if applicable).

The sort-union-types rule documentation lacks a migration notice for the customGroups option, whereas sort-classes includes one at lines 641–667 of its file. If the customGroups API for union types was also changed (from object-based to array-based), please add a similar migration notice to aid users upgrading to v5.0.0.

Does the sort-union-types rule's customGroups option have breaking API changes in v5.0.0? If so, a migration notice similar to the one in sort-classes.mdx should be added.

docs/content/rules/sort-classes.mdx (5)

327-338: Type definition for groups option is consistent with sort-union-types.mdx.

The union type mirrors the structure from sort-union-types documentation, ensuring consistency across rules. Per-group overrides (newlinesBetween objects and type overrides) are clearly represented.


342-359: Comprehensive default groups configuration is well-documented.

The default groups array is extensive and covers all selector and modifier combinations for class members (index-signature, static properties, accessors, constructor, methods, etc.). The structure is clear and the comments explain each group's purpose.

Please verify that this default groups configuration exactly matches the actual implementation in rules/sort-classes/index.ts or the corresponding rule file to ensure documentation accuracy.


605-618: Per-group overrides section aligns well with sort-union-types documentation.

The "Group with overridden settings" section provides a clear, concise example of overriding the type option for a specific group. The example demonstrates the feature without unnecessary complexity.


641-667: Migration notice for breaking customGroups API change is helpful and clear.

The notice at lines 641–667 effectively communicates the breaking change from object-based to array-based customGroups configuration. The before/after code example makes migration straightforward for users upgrading to v5.0.0.


738-783: Verify code fence language and syntax highlighting.

The customGroups example uses ts language specifier. Ensure the TypeScript syntax in the example is highlighted correctly and that the code block is properly formatted for readability on the documentation site.

Please confirm that the code fence rendering (lines 738–783) displays correctly on the documentation site and that TypeScript syntax highlighting is applied appropriately.

test/rules/sort-classes.test.ts (3)

4011-4021: Numeric newlinesBetween migration LGTM.

Using numeric values (0/1/2) and 'ignore' per-group/global is clear and consistent with the new API. No issues spotted.

Also applies to: 8661-8671, 13245-13255


13998-14028: Great test for per‑group overrides.

Verifies that a group can override the global type. This guards the new options shape well.


4279-4324: Partition + newlinesBetween = 0: scenario reads well.

Good coverage to ensure spacing fixes don’t cross partitions. No changes requested.

Also applies to: 8930-8974, 13513-13559

test/rules/sort-exports.test.ts (2)

527-553: Good coverage for per-group option overrides.

Validates that a group-level type override works with global type: 'unsorted'. LGTM.


867-921: Solid test for newlinesBetween: 0 removal behavior.

Covers both spacing diagnostics and reordering. LGTM.

docs/content/rules/sort-maps.mdx (1)

301-314: Good: per‑group overrides section reads clearly.

No changes requested. Consider noting if order/fallbackSort can also be overridden here for parity with customGroups.

docs/content/rules/sort-interfaces.mdx (1)

699-718: Nice example with group names; LGTM.

Clear migration to array-based customGroups and combined groups.

docs/content/rules/sort-sets.mdx (2)

284-284: Default groups update to ['literal'] — LGTM.


303-316: Per‑group overrides section reads well.

No changes requested.

docs/content/rules/sort-enums.mdx (1)

261-274: Per‑group overrides example — LGTM.

test/rules/sort-enums.test.ts (1)

1288-1330: Tests demonstrate 'ignore' allowed in group newlines descriptors. Sync docs.

Multiple cases use { newlinesBetween: 'ignore' } inside groups. Please ensure all rule docs (enums, interfaces, objects, sets, maps, exports) reflect this union at group level.

Also applies to: 1390-1435, 1437-1486

docs/content/rules/sort-objects.mdx (1)

712-731: Example reads well; migration is clear.

docs/content/rules/sort-exports.mdx (2)

183-194: Good partitionByNewLine example.

Reads clearly.


262-301: commentAbove docs are clear and actionable.

Nice addition; behavior and auto-fix semantics are well explained.

test/rules/sort-array-includes.test.ts (4)

262-312: Group-order error coverage for spread vs unknown looks correct

The added groups: ['spread'] plus leftGroup/rightGroup and messageId: 'unexpectedArrayIncludesGroupOrder' assertions exercise the new group-order diagnostics consistently across alphabetical, natural, and line-length modes. No issues spotted.

Also applies to: 2070-2120, 3825-3873


840-871: Good regression test for per-group type override

Using global type: 'unsorted' with groups: [{ type: 'alphabetical', group: 'unknown' }] is a nice way to lock in that group-local sort settings win over the global mode. The expectations for both error and output match that intent.


1366-1395: newlinesBetween: 0 behavior is well specified and tested

These cases correctly assert:

  • extra-spacing diagnostics when blank lines exist between groups with newlinesBetween: 0
  • that auto-fix removes those blank lines without disturbing order semantics.

The triplicated coverage for all three sort modes is thorough.

Also applies to: 3110-3169, 4865-4924


1771-1819: Partition boundaries preserved despite newlinesBetween: 0

The “preserves partition boundaries regardless of newlinesBetween 0” tests correctly lock in that partitionByComment: true segments are never merged or reordered across the partition comment, even when global newlines are forced to zero. Behavior and expectations are consistent.

Also applies to: 3545-3593, 5300-5348

test/rules/sort-decorators.test.ts (6)

471-533: Per-group override test for decorators matches the intended API

The “allows overriding options in groups” case mirrors the array-includes behavior: a global type: 'unsorted' with groups: [{ type: 'alphabetical', group: 'unknown' }] and 5 contexts covered via duplicate5Times. Error IDs and outputs look consistent.


535-623: Solid coverage of elementNamePattern variants in custom groups

The it.each block that exercises string, array, and regex (including in arrays) patterns for elementNamePattern is a good regression guard that the custom grouping logic accepts all supported shapes and emits unexpectedDecoratorsGroupOrder with the right leftGroup/rightGroup.


624-914: Custom-group sort/type overrides and unsorted behavior are well tested

The new tests around:

  • overriding type/order for a Foo-containing group,
  • per-group fallbackSort on ties, and
  • preserving original order for type: 'unsorted' groups and negative regex patterns

together give strong coverage of the richer customGroups API for decorators. Expectations and options structures are coherent with the docs.


916-1271: Newline behavior between decorator groups is exhaustively covered

The newlinesBetween tests for decorators (0 vs 1 vs 2 vs 'ignore', plus inline overrides in groups) carefully distinguish:

  • extra vs missed spacing diagnostics,
  • precedence between global and inline settings, and
  • the “accept any spacing” combinations.

This aligns with the array-includes tests and should make regressions here unlikely.


1361-1555: newlinesInside and partitionByNewLine semantics are nailed down

The newlinesInside: 1 / 0 tests, plus “sorts within newline-separated partitions” and “preserves partition boundaries regardless of newlinesBetween 0”, give clear expectations for:

  • intra-group spacing constraints, and
  • how newline partitions limit reordering.

The chosen error IDs (missedSpacingBetweenDecorators / extraSpacingBetweenDecorators / unexpectedDecoratorsOrder) look correct for each scenario.


2877-2927: Natural-mode JSDoc handling stays consistent with alphabetical tests

The natural-sort variants of “handles JSDoc comments before decorators correctly” now mirror the alphabetical ones, including the “Not a JSDoc comment” case. This keeps comment movement semantics uniform across sort types.

docs/content/rules/sort-decorators.mdx (3)

270-337: groups shape and per-group override docs align with tests

The documented groups union (strings, arrays, { newlinesBetween }, and { group, type }) plus the “Group with overridden settings” and “Newlines between groups” sections match how the tests configure per-group overrides and inline newline rules. No changes needed here.


441-453: Docs example for customGroups now matches the new array API

The migration snippet from the old object-based customGroups to the new array-of-definitions form is clear and matches how tests configure decorators custom groups. Nice addition.


441-454: Updated default config snippet reflects new options

The “Usage” code samples show partitionByNewLine, partitionByComment, newlinesBetween, groups: [], and customGroups: [] with sensible defaults that align with the tests. This is consistent with the new rule surface.

Also applies to: 458-484

docs/content/rules/sort-imports.mdx (3)

285-315: Comprehensive API expansion well-documented.

The redesigned groups option (lines 288–300) with union types for string, string[], newlinesBetween, and per-group config objects is clearly specified. The default groups example (lines 304–315) properly reflects the array-based structure. New selector (tsconfig-path, line 338) and modifiers (multiline, singleline, lines 360–361) fit logically into the existing hierarchy.


452-491: New sections on per-group overrides and newline control are well-explained.

Both "Group with overridden settings" (lines 452–472) and "Newlines between groups" (lines 474–491) clearly document the new per-group configuration capabilities: group, commentAbove, type fields, and placement of newlinesBetween objects as distinct array elements. Examples are practical and reinforce the intent.


602-626: Example code properly demonstrates array-based customGroups migration.

The example (lines 602–626) shows migration from object to array-based customGroups with groupName and elementNamePattern properties. The react and lodash group definitions are clear and align with the documented API.

docs/content/rules/sort-jsx-props.mdx (5)

270-283: Array-based customGroups API properly documented.

The migration from object-map to array-based format with groupName and elementNamePattern is clear. Each group definition follows the documented interface correctly.


318-329: Updated groups type definition aligns with sort-imports.mdx.

The expanded union type for groups (lines 318–329) supports string, string[], newlinesBetween, and per-group config objects, consistent with the sort-imports rule documentation.


356-369: New "Group with overridden settings" section is clear.

The section (lines 356–369) properly documents per-group type overrides with a practical example showing how 'shorthand' props can remain unsorted while multiline props are sorted.


530-530: Config examples correctly updated to array-based customGroups default.

Both flat and legacy config examples (lines 530, 560) now show customGroups: [] reflecting the new API default, replacing the prior object-based format.

Also applies to: 560-560


582-582: Test source link updated to new path.

Line 582 updates the test source link to test/rules/sort-jsx-props.test.ts, reflecting the migration to Vitest as documented in the PR objectives.

Comment on lines +148 to +159
### partitionByComment

<sub>default: `false`</sub>

Enables the use of comments to separate class decorators into logical groups.

- `true` — All comments will be treated as delimiters, creating partitions.
- `false` — Comments will not be used as delimiters.
- `RegExpPattern = string | { pattern: string; flags: string}` — A regexp pattern to specify which comments should act as delimiters.
- `RegExpPattern[]` — A list of regexp patterns to specify which comments should act as delimiters.
- `{ block: boolean | RegExpPattern | RegExpPattern[]; line: boolean | RegExpPattern | RegExpPattern[] }` — Specify which block and line comments should act as delimiters.

Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Replace “class decorators” with “heritage clauses”.

This rule is about extends/implements. The section mistakenly refers to “class decorators”.

- Enables the use of comments to separate class decorators into logical groups.
+ Enables the use of comments to separate heritage clauses into logical groups.
🤖 Prompt for AI Agents
In docs/content/rules/sort-heritage-clauses.mdx around lines 148 to 159, the
text incorrectly refers to “class decorators”; update those occurrences to
“heritage clauses” so the description reads that comments separate heritage
clauses (i.e., extends/implements). Keep the rest of the option descriptions
unchanged and ensure the heading/subtext semantics remain intact.

Comment on lines 547 to 560
#### Group with overridden settings
You may directly override options for a specific group by using an object with the `group` property and other option overrides.
- `type` — Overrides the [`type`](#type) option for that group.
```ts
{
groups: [
'method',
{ group: 'multiline-member', type: 'unsorted' }, // Elements from this group will not be sorted
]
}
```
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Unclosed code fence above breaks MDX rendering.

The “Example 2” code block started earlier isn’t closed before this heading. Close the block (and the interface brace if needed) to avoid layout/anchor issues.

 interface Interface {
   // 'index-signature'
   [key: string]: any;
   // 'optional-property'
   description?: string;
   // 'required-method'
   method(): string
-```
+}
+```

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In docs/content/rules/sort-interfaces.mdx around lines 547 to 560, the prior
example's code fence (and the closing interface brace if the example left one
open) is missing which breaks MDX rendering; fix it by adding the required
closing brace(s) and terminating the fenced code block (```), ensuring the
example is syntactically complete before the "Group with overridden settings"
heading so the MDX parses correctly.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

♻️ Duplicate comments (1)
rules/sort-imports/types.ts (1)

37-40: Fix malformed JSDoc @default tag for tsconfig.filename.

The JSDoc currently splits the @default tag across lines and leaves a stray quote (tsconfig.json'.), which makes the comment malformed and less useful to tooling.

Consider updating it to a standard @default annotation:

-        /**
-         * Optional filename of the TypeScript config file. `@default`
-         * tsconfig.json'.
-         */
+        /**
+         * Optional filename of the TypeScript config file.
+         * @default 'tsconfig.json'
+         */
🧹 Nitpick comments (3)
rules/sort-object-types/types.ts (1)

164-179: Consider reviewing the 'multiline' entry in AllowedModifiersPerSelector.

The AllowedModifiersPerSelector interface includes a 'multiline' key at line 174, but 'multiline' is not a valid selector in the Selector union type (lines 144-148). Since BaseSingleCustomGroup<T extends Selector> constrains T to the Selector type, this entry appears unreachable through the type system.

While this may be pre-existing code unrelated to the current PR, it could be confusing for maintainers. Consider removing the unused 'multiline' entry or clarifying its purpose if it serves a specific role.

rules/sort-imports/types.ts (1)

170-188: Selectors/modifiers and JSON schema are coherent; consider tightening type/schema alignment.

The following pieces line up well:

  • Selector and Modifier unions now explicitly include all string literal variants used by the rule (including the new singleline / multiline modifiers).
  • allSelectors and allModifiers enumerate exactly those variants, which is important for validateGeneratedGroupsConfiguration and schema generation.
  • singleCustomGroupJsonSchema uses buildCustomGroupModifiersJsonSchema(allModifiers) and buildCustomGroupSelectorJsonSchema(allSelectors), so schema validation stays in sync with the unions.

Two optional improvements you might consider:

  1. Derive union types from the arrays to avoid future drift, e.g.:

    export const allSelectors = [
      'side-effect-style',
      'tsconfig-path',
      // ...
    ] as const
    
    export type Selector = (typeof allSelectors)[number]

    and similarly for modifiers. That guarantees compile-time alignment between the arrays and the unions.

  2. Align SingleCustomGroup with the JSON schema: the schema exposes both elementValuePattern and elementNamePattern, while SingleCustomGroup here only types elementNamePattern. If elementValuePattern is intentionally unsupported for sort-imports, consider dropping it from this schema; otherwise, add it as an optional property to SingleCustomGroup so TS users and JSON schema see the same surface.

Also applies to: 205-216, 247-252, 331-342, 348-352

rules/sort-imports.ts (1)

115-123: Consider guarding tsconfig resolution on options.tsconfig rather than rootDir truthiness.

The current logic only resolves a tsconfig when options.tsconfig?.rootDir is truthy:

let tsconfigRootDirectory = options.tsconfig?.rootDir
let tsConfigOutput = tsconfigRootDirectory
  ? readClosestTsConfigByPath({ /* ... */ })
  : null

This will skip resolution if someone (perhaps accidentally) configures rootDir: ''. If you want any provided tsconfig object to be honored regardless of whether rootDir is an empty string or './', consider keying the condition off the presence of options.tsconfig instead:

-    let tsconfigRootDirectory = options.tsconfig?.rootDir
-    let tsConfigOutput = tsconfigRootDirectory
-      ? readClosestTsConfigByPath({
-          tsconfigFilename: options.tsconfig?.filename ?? 'tsconfig.json',
-          tsconfigRootDir: tsconfigRootDirectory,
+    let tsConfig = options.tsconfig
+    let tsConfigOutput = tsConfig
+      ? readClosestTsConfigByPath({
+          tsconfigFilename: tsConfig.filename ?? 'tsconfig.json',
+          tsconfigRootDir: tsConfig.rootDir,
           filePath: context.physicalFilename,
           contextCwd: context.cwd,
         })
       : null

This also avoids repeating the optional chaining on options.tsconfig.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 513d13e and 98404bf.

📒 Files selected for processing (3)
  • rules/sort-imports.ts (9 hunks)
  • rules/sort-imports/types.ts (6 hunks)
  • rules/sort-object-types/types.ts (3 hunks)
🧰 Additional context used
🧬 Code graph analysis (3)
rules/sort-object-types/types.ts (3)
types/common-options.ts (3)
  • RegexOption (458-458)
  • CustomGroupsOption (103-134)
  • FallbackSortOption (274-286)
rules/sort-objects/types.ts (1)
  • SingleCustomGroup (122-138)
types/join-with-dash.ts (1)
  • JoinWithDash (4-4)
rules/sort-imports/types.ts (2)
types/common-options.ts (1)
  • CustomGroupsOption (103-134)
rules/sort-jsx-props/types.ts (2)
  • SingleCustomGroup (80-105)
  • Selector (117-117)
rules/sort-imports.ts (7)
rules/sort-imports/types.ts (5)
  • Options (29-141)
  • allSelectors (311-325)
  • allModifiers (331-342)
  • Selector (174-187)
  • Modifier (205-215)
utils/validate-newlines-and-partition-configuration.ts (1)
  • validateNewlinesAndPartitionConfiguration (98-119)
rules/sort-imports/validate-side-effects-configuration.ts (1)
  • validateSideEffectsConfiguration (19-48)
utils/is-node-on-single-line.ts (1)
  • isNodeOnSingleLine (9-11)
utils/common-json-schemas.ts (1)
  • buildCustomGroupsArrayJsonSchema (324-373)
utils/generate-predefined-groups.ts (1)
  • generatePredefinedGroups (23-56)
utils/compute-group.ts (1)
  • computeGroup (77-115)
🔇 Additional comments (10)
rules/sort-object-types/types.ts (4)

35-39: LGTM!

The new declarationCommentMatchesPattern field is well-documented and follows the established pattern naming convention.


53-57: LGTM!

The new hasNumericKeysOnly field is well-defined and clearly documented.


60-67: LGTM!

The migration to array-based CustomGroupsOption aligns with the PR objectives. The type parameters and additional options are well-structured.


231-240: LGTM!

The new PropertyGroup type definition follows the same pattern as other group types and properly replaces the deprecated MultilineGroup. The JSDoc documentation clearly explains its purpose.

rules/sort-imports/types.ts (1)

46-48: Custom groups option wiring looks correct.

customGroups: CustomGroupsOption<SingleCustomGroup> is consistent with CustomGroupsOption from types/common-options.ts and the SingleCustomGroup definition here, so the public options surface for sort-imports matches the shared custom-groups abstraction.

rules/sort-imports.ts (5)

43-43: Single-line vs multiline modifiers are wired consistently.

Using isNodeOnSingleLine(node) to always append exactly one of 'singleline' or 'multiline' to modifiers keeps the modifier set mutually exclusive for line-shape, and matches the new Modifier union and allModifiers in rules/sort-imports/types.ts. This should integrate cleanly with group computation and validation.

Also applies to: 214-218


67-71: defaultOptions typing and reuse across rule/meta look solid.

Typing defaultOptions as:

Required<Omit<Options[number], 'maxLineLength' | 'tsconfig'>> &
  Pick<Options[number], 'maxLineLength' | 'tsconfig'>

ensures all non-maxLineLength/tsconfig fields are explicitly populated while keeping those two optional. Reusing the same defaultOptions object for both meta.defaultOptions and the rule’s defaultOptions keeps the public API and runtime defaults in sync.

Also applies to: 450-455


106-113: Custom-groups flow, group computation, and schema wiring are coherent.

A few related pieces look well-aligned:

  • validateGeneratedGroupsConfiguration({ selectors: allSelectors, modifiers: allModifiers, options }) ensures the resolved options (defaults + user config) are validated against the authoritative selector/modifier sets from rules/sort-imports/types.ts.
  • getCustomGroupOverriddenOptions({ groupIndex, options }) is now called with the full resolved options, and the subsequent logic preserves the "side-effect groups are unsorted when sortSideEffects is false" behavior by overriding type to 'unsorted' only for pure side-effect groups.
  • customGroups in the schema uses buildCustomGroupsArrayJsonSchema({ singleCustomGroupJsonSchema }), so the runtime JSON schema now matches the new array-based custom-groups shape defined in rules/sort-imports/types.ts.
  • computeGroupExceptUnknown cleanly wraps generatePredefinedGroups and computeGroup, returning null for the 'unknown' case; the caller then normalizes this back to 'unknown' via ?? 'unknown', so behavior stays the same while providing a reusable helper if needed elsewhere.

Overall, the custom-groups pipeline (options → validation → JSON schema → runtime group computation) looks consistent.

Also applies to: 312-338, 422-424, 450-455, 530-561


355-369: Passing resolved options into reportAllErrors is a good enhancement.

Including options in the reportAllErrors call gives the reporting layer access to the fully-resolved configuration (defaults + user overrides), which can be useful for context-aware diagnostics or future behavior toggles, without changing the core sorting logic.


372-381: Optional chaining on VariableDeclaration init prevents crashes.

The additional ?. on node.declarations[0].init avoids accessing .type on undefined when handling VariableDeclarations that don’t have an initializer, while preserving the existing require-call detection logic.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
docs/content/rules/sort-jsx-props.mdx (1)

299-307: tagMatchesPattern example uses invalid regexp syntax.

The example value '*Component$' is not a valid JavaScript regular expression pattern (a leading * is illegal). If the intent is “names ending with Component”, it should be:

-        tagMatchesPattern: '*Component$',
+        tagMatchesPattern: '.*Component$',

(or simply 'Component$' if a .* prefix is unnecessary).

♻️ Duplicate comments (12)
docs/content/rules/sort-jsx-props.mdx (1)

269-286: Fix allNamesMatchPattern RGB regex anchoring.

'^r|g|b$' is parsed as (^r) | g | (b$), so it will match many unintended names (any containing g, any ending with b, etc.). To match only props named exactly 'r', 'g', or 'b', wrap the alternation in a single anchored group:

-        allNamesMatchPattern: '^r|g|b$',
+        allNamesMatchPattern: '^(?:r|g|b)$',
docs/content/rules/sort-heritage-clauses.mdx (2)

148-159: Replace "class decorators" with "heritage clauses".

This section incorrectly refers to "class decorators" when it should refer to "heritage clauses" (i.e., extends/implements clauses).

Apply this diff:

-Enables the use of comments to separate class decorators into logical groups.
+Enables the use of comments to separate heritage clauses into logical groups.

308-319: Verify type union completeness for CustomGroupAnyOfDefinition.

The type option on line 310 is missing 'custom', which is documented as a valid option elsewhere in this file (line 73). For consistency with CustomGroupDefinition (lines 293-300), ensure the type union includes all valid options.

Apply this diff:

 interface CustomGroupAnyOfDefinition {
   groupName: string
-  type?: 'alphabetical' | 'natural' | 'line-length' | 'unsorted'
+  type?: 'alphabetical' | 'natural' | 'line-length' | 'custom' | 'unsorted'
   order?: 'asc' | 'desc'
   fallbackSort?: { type: string; order?: 'asc' | 'desc' }
   newlinesInside?: number
rules/sort-imports/types.ts (1)

24-38: Fix malformed JSDoc comment.

The JSDoc comment has a malformed @default annotation with mismatched quotes.

Apply this diff:

         /**
-         * Optional filename of the TypeScript config file. `@default`
-         * tsconfig.json'.
+         * Optional filename of the TypeScript config file.
+         * @default 'tsconfig.json'
          */
docs/content/rules/sort-export-attributes.mdx (2)

146-157: Remove unsupported newlinesBetween values.

The documentation lists 'always' and 'never' as valid values, but according to past review comments, the actual implementation only supports 'ignore' and number.

Apply this diff:

-<sub>type: `number | 'ignore' | 'always' | 'never'`</sub>
+<sub>type: `number | 'ignore'`</sub>
 <sub>default: `'ignore'`</sub>
 
 Controls newlines between groups:
 
 - `'ignore'` — Do not report spacing issues.
-- `'always'` — Require a blank line between groups, forbid blank lines inside a group.
-- `'never'` — Forbid blank lines between groups.
 - `number` — Require exactly that many newlines between groups; forbid inside a group.

226-244: Fix newlinesInside type definition.

The type annotation shows 'always' | 'never' | number, but according to past review comments, the implementation only accepts number.

Apply this diff:

   // Optional per-group overrides:
   type?: 'alphabetical' | 'natural' | 'line-length' | 'custom' | 'unsorted'
   order?: 'asc' | 'desc'
   fallbackSort?: { type: string; order?: 'asc' | 'desc' }
-  newlinesInside?: 'always' | 'never' | number
+  newlinesInside?: number
 }[]
docs/content/rules/sort-modules.mdx (1)

501-545: Fix trailing . in elementNamePattern in the customGroups example

In the input-types-and-interfaces example, both elementNamePattern: 'Input'. and elementNamePattern: 'Input'. end with a trailing dot, which makes the snippet invalid TypeScript. Drop the dot so it becomes elementNamePattern: 'Input'.

The “Test source” link now correctly targets test/rules/sort-modules.test.ts.

rules/sort-export-attributes.ts (1)

9-40: Wire in newlinesBetweenValueGetter so spacing/newline diagnostics work

The rule collects attributes, partitions them, and calls reportAllErrors, but it never supplies newlinesBetweenValueGetter. That means the newlinesBetween option and the spacing-related messages (missedSpacingBetweenExportAttributes / extraSpacingBetweenExportAttributes) cannot function as intended.

You already have getLinesBetween in the shared utils; the rule just needs to hook it up.

Suggested patch:

@@
-import { sortNodesByGroups } from '../utils/sort-nodes-by-groups'
+import { sortNodesByGroups } from '../utils/sort-nodes-by-groups'
+import { getLinesBetween } from '../utils/get-lines-between'
@@
       for (let nodes of formattedMembers) {
@@
         function createSortNodesExcludingEslintDisabled(
           sortingNodes: SortExportAttributesSortingNode[],
         ) {
@@
         }
 
         reportAllErrors<MessageId>({
           availableMessageIds: {
             missedSpacingBetweenMembers: 'missedSpacingBetweenExportAttributes',
             extraSpacingBetweenMembers: 'extraSpacingBetweenExportAttributes',
             unexpectedGroupOrder: 'unexpectedExportAttributesGroupOrder',
             unexpectedOrder: 'unexpectedExportAttributesOrder',
           },
           sortNodesExcludingEslintDisabled:
             createSortNodesExcludingEslintDisabled(nodes),
+          newlinesBetweenValueGetter: (left, right) =>
+            getLinesBetween(sourceCode, left, right),
           sourceCode,
           options,
           context,
           nodes,
         })
       }

After this change, newlinesBetween (both global and per-group) should start producing the expected spacing errors for export attributes. Please run the sort-export-attributes tests to confirm behavior.

Also applies to: 86-163

rules/sort-enums/types.ts (1)

35-48: Clarify sortByValue JSDoc to document all three string literals.

The type now exposes 'ifNumericEnum' | 'always' | 'never', but the comment only explains "always" and "never" and doesn’t describe what 'ifNumericEnum' does. That makes the generated docs and types harder to interpret.

Consider updating the block along these lines:

-    /**
-     * Whether to sort enum members by their values instead of names. When
-     * "always", compares enum values; when "never", compares enum member
-     * names.
-     *
-     * @default ifNumericEnum
-     */
-    sortByValue: 'ifNumericEnum' | 'always' | 'never'
+    /**
+     * Controls when enum members should be ordered by their values instead of their names.
+     *
+     * - `'always'` — compare enum member values for every enum.
+     * - `'never'` — keep name-based ordering regardless of values.
+     * - `'ifNumericEnum'` — sort by value only when every member has a numeric initializer; otherwise, sort by name.
+     *
+     * @default 'ifNumericEnum'
+     */
+    sortByValue: 'ifNumericEnum' | 'always' | 'never'
docs/content/rules/sort-interfaces.mdx (1)

538-546: Close the interface in “Example 2” for a syntactically complete snippet.

The code block ends without a closing } for interface Interface, which makes the example invalid TypeScript even though the fence is now closed. Adding the brace keeps the example self‑contained:

 interface Interface {
   // 'index-signature'
   [key: string]: any;
   // 'optional-property'
   description?: string;
   // 'required-method'
   method(): string
-```
+}
+```
docs/content/rules/sort-decorators.mdx (2)

380-387: Correct the TypeScript interface types.

The CustomGroupDefinition interface has incorrect type definitions that were previously flagged:

  1. fallbackSort should use a specific type union instead of type: string
  2. newlinesInside should accept 'always' | 'never' | number instead of just number

These types should match the runtime type definitions.

Based on learnings


547-547: Verify the test source link path.

A previous review flagged this link as potentially pointing to the wrong path. Ensure it correctly references test/rules/sort-decorators.test.ts.

Based on learnings

🧹 Nitpick comments (8)
docs/content/rules/sort-jsx-props.mdx (1)

357-371: Align group names in overridden-settings example with documented selector/modifier format.

Earlier in the doc you state that selectors end with prop and give shorthand-prop as the example group name; here the example uses bare 'multiline' and 'shorthand', which can be confusing. To keep terminology consistent with the rule’s group naming (selector + modifiers), consider:

-  groups: [
-    'multiline',
-    { group: 'shorthand', type: 'unsorted' }, // Elements from this group will not be sorted
-  ]
+  groups: [
+    'multiline-prop',
+    { group: 'shorthand-prop', type: 'unsorted' }, // Elements from this group will not be sorted
+  ]
rules/sort-jsx-props/types.ts (1)

47-52: Align selector JSDoc with the narrowed Selector type.

SingleCustomGroup.selector’s comment still claims it “can be 'prop', 'multiline', or 'shorthand'”, but Selector is now PropertySelector ('prop' only), with multiline/shorthand modeled via the modifiers array instead. Please update this JSDoc (and any related docs) so it reflects that selector is just 'prop' and multiline/shorthand are expressed exclusively as modifiers.

Also applies to: 90-95

rules/sort-object-types/types.ts (1)

141-156: Consider removing the now-unused ‘multiline’ selector mapping for clarity

With PropertyGroup added and the Group union now based on IndexSignatureGroup | PropertyGroup | MethodGroup | MemberGroup, there is no MultilineSelector in Selector and SingleCustomGroup no longer uses a 'multiline' selector. The AllowedModifiersPerSelector['multiline'] entry therefore appears unreachable and can be removed (along with its comment) to reduce mental overhead for future contributors.

Also applies to: 199-207, 208-233

docs/content/rules/sort-import-attributes.mdx (1)

226-242: Ensure CustomGroup doc type matches the actual rule typings

The CustomGroup example type (including elementNamePattern and newlinesInside?: 'always' | 'never' | number) looks reasonable, but it needs to stay exactly in sync with SingleCustomGroup / CustomGroupsOption in rules/sort-import-attributes/types.ts.

Please quickly confirm that:

  • elementNamePattern’s documented union matches the RegexOption/pattern type used in the rule, and
  • newlinesInside’s allowed values reflect what the implementation actually supports.

If there’s any drift, updating either the typings or this snippet will keep users from guessing.

docs/content/rules/sort-sets.mdx (1)

271-283: Consider documenting 'ignore' for per‑group newlinesBetween if it’s supported.

The groups type snippet currently restricts { newlinesBetween: ... } to number, while the global newlinesBetween option allows number | 'ignore'. If group-level objects also accept 'ignore' (as other rules’ tests suggest), it’s worth reflecting that here to avoid under‑documenting the API.

Also applies to: 304-318

docs/content/rules/sort-interfaces.mdx (1)

421-435: Optional: align per‑group newlinesBetween docs with the global option.

The groups type currently shows { newlinesBetween: number }, while the global newlinesBetween option supports number | 'ignore'. If the implementation also accepts 'ignore' in group objects (as tests for other rules suggest), consider reflecting that here to avoid confusion between the two surfaces.

Also applies to: 548-562

test/rules/sort-enums.test.ts (1)

552-655: New tests thoroughly exercise sortByValue, per‑group overrides, and newlinesBetween semantics.

The added cases cover all three sortByValue modes, complex numeric enum detection, global vs per‑group newlinesBetween, and interactions with partitions and custom groups, which should make regressions in these areas unlikely. If you ever want to trim duplication, many of the newlinesBetween scenarios are structurally identical across the alphabetical/natural/line‑length suites and could be parameterized with describe.each, but that’s optional.

Also applies to: 1157-1615, 2688-3126, 4163-4601

docs/content/rules/sort-exports.mdx (1)

215-229: Docs for groups look good; you might clarify per‑group newlinesBetween type.

The new groups union and commentAbove explanation nicely match the rule’s richer grouping API. One small nit: the snippet types { newlinesBetween: number }, while the top-level newlinesBetween option allows number | 'ignore'. If group-level objects also accept 'ignore', consider reflecting that here so the two surfaces stay in sync.

Also applies to: 263-303

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 98404bf and f9919cb.

📒 Files selected for processing (48)
  • docs/content/rules/sort-array-includes.mdx (5 hunks)
  • docs/content/rules/sort-classes.mdx (4 hunks)
  • docs/content/rules/sort-decorators.mdx (6 hunks)
  • docs/content/rules/sort-enums.mdx (6 hunks)
  • docs/content/rules/sort-export-attributes.mdx (1 hunks)
  • docs/content/rules/sort-exports.mdx (4 hunks)
  • docs/content/rules/sort-heritage-clauses.mdx (6 hunks)
  • docs/content/rules/sort-import-attributes.mdx (1 hunks)
  • docs/content/rules/sort-imports.mdx (6 hunks)
  • docs/content/rules/sort-interfaces.mdx (8 hunks)
  • docs/content/rules/sort-intersection-types.mdx (6 hunks)
  • docs/content/rules/sort-jsx-props.mdx (7 hunks)
  • docs/content/rules/sort-maps.mdx (3 hunks)
  • docs/content/rules/sort-modules.mdx (4 hunks)
  • docs/content/rules/sort-named-exports.mdx (3 hunks)
  • docs/content/rules/sort-named-imports.mdx (3 hunks)
  • docs/content/rules/sort-object-types.mdx (8 hunks)
  • docs/content/rules/sort-objects.mdx (9 hunks)
  • docs/content/rules/sort-sets.mdx (5 hunks)
  • docs/content/rules/sort-switch-case.mdx (1 hunks)
  • docs/content/rules/sort-union-types.mdx (5 hunks)
  • docs/content/rules/sort-variable-declarations.mdx (4 hunks)
  • rules/sort-array-includes/types.ts (2 hunks)
  • rules/sort-classes/types.ts (2 hunks)
  • rules/sort-decorators/types.ts (1 hunks)
  • rules/sort-enums/types.ts (2 hunks)
  • rules/sort-export-attributes.ts (1 hunks)
  • rules/sort-export-attributes/types.ts (1 hunks)
  • rules/sort-exports/types.ts (2 hunks)
  • rules/sort-heritage-clauses/types.ts (1 hunks)
  • rules/sort-import-attributes.ts (1 hunks)
  • rules/sort-import-attributes/types.ts (1 hunks)
  • rules/sort-imports/types.ts (5 hunks)
  • rules/sort-jsx-props/types.ts (4 hunks)
  • rules/sort-maps/types.ts (2 hunks)
  • rules/sort-modules/types.ts (2 hunks)
  • rules/sort-named-exports/types.ts (2 hunks)
  • rules/sort-named-imports/types.ts (2 hunks)
  • rules/sort-object-types/build-node-value-getter.ts (2 hunks)
  • rules/sort-object-types/types.ts (5 hunks)
  • rules/sort-objects/types.ts (6 hunks)
  • rules/sort-union-types/types.ts (2 hunks)
  • rules/sort-variable-declarations/types.ts (2 hunks)
  • test/rules/sort-array-includes.test.ts (42 hunks)
  • test/rules/sort-classes.test.ts (27 hunks)
  • test/rules/sort-decorators.test.ts (2 hunks)
  • test/rules/sort-enums.test.ts (41 hunks)
  • test/rules/sort-export-attributes.test.ts (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • docs/content/rules/sort-switch-case.mdx
🚧 Files skipped from review as they are similar to previous changes (7)
  • docs/content/rules/sort-intersection-types.mdx
  • test/rules/sort-export-attributes.test.ts
  • rules/sort-import-attributes.ts
  • docs/content/rules/sort-named-imports.mdx
  • test/rules/sort-classes.test.ts
  • rules/sort-export-attributes/types.ts
  • rules/sort-heritage-clauses/types.ts
🧰 Additional context used
🧬 Code graph analysis (18)
rules/sort-object-types/build-node-value-getter.ts (1)
utils/unreachable-case-error.ts (1)
  • UnreachableCaseError (31-43)
rules/sort-enums/types.ts (3)
types/common-groups-options.ts (1)
  • CommonGroupsOptions (7-19)
types/common-partition-options.ts (1)
  • CommonPartitionOptions (3-15)
types/common-options.ts (1)
  • CommonOptions (23-73)
rules/sort-maps/types.ts (3)
types/common-groups-options.ts (1)
  • CommonGroupsOptions (7-19)
types/common-partition-options.ts (1)
  • CommonPartitionOptions (3-15)
types/common-options.ts (1)
  • CommonOptions (23-73)
rules/sort-decorators/types.ts (5)
types/common-groups-options.ts (1)
  • CommonGroupsOptions (7-19)
types/common-partition-options.ts (1)
  • CommonPartitionOptions (3-15)
types/common-options.ts (2)
  • CommonOptions (23-73)
  • RegexOption (464-464)
types/sorting-node.ts (1)
  • SortingNode (18-102)
utils/common-json-schemas.ts (1)
  • regexJsonSchema (242-251)
rules/sort-imports/types.ts (4)
types/common-options.ts (2)
  • RegexOption (464-464)
  • CommonOptions (23-73)
types/common-groups-options.ts (1)
  • CommonGroupsOptions (7-19)
types/common-partition-options.ts (1)
  • CommonPartitionOptions (3-15)
utils/sort-nodes-by-dependencies.ts (1)
  • SortingNodeWithDependencies (16-21)
rules/sort-array-includes/types.ts (3)
types/common-groups-options.ts (1)
  • CommonGroupsOptions (7-19)
types/common-partition-options.ts (1)
  • CommonPartitionOptions (3-15)
types/common-options.ts (1)
  • CommonOptions (23-73)
rules/sort-import-attributes/types.ts (6)
rules/sort-export-attributes/types.ts (4)
  • SingleCustomGroup (16-25)
  • Group (32-32)
  • singleCustomGroupJsonSchema (35-38)
  • Options (40-44)
types/common-options.ts (2)
  • RegexOption (464-464)
  • CommonOptions (23-73)
utils/common-json-schemas.ts (1)
  • regexJsonSchema (242-251)
types/common-groups-options.ts (1)
  • CommonGroupsOptions (7-19)
types/common-partition-options.ts (1)
  • CommonPartitionOptions (3-15)
types/sorting-node.ts (1)
  • SortingNode (18-102)
rules/sort-export-attributes.ts (17)
utils/create-eslint-rule.ts (1)
  • createEslintRule (32-35)
utils/is-sortable.ts (1)
  • isSortable (7-9)
utils/get-settings.ts (1)
  • getSettings (62-107)
utils/complete.ts (1)
  • complete (30-45)
utils/validate-custom-sort-configuration.ts (1)
  • validateCustomSortConfiguration (29-37)
utils/validate-generated-groups-configuration.ts (1)
  • validateGeneratedGroupsConfiguration (75-93)
utils/validate-newlines-and-partition-configuration.ts (1)
  • validateNewlinesAndPartitionConfiguration (98-119)
utils/get-eslint-disabled-lines.ts (1)
  • getEslintDisabledLines (45-97)
utils/compute-group.ts (1)
  • computeGroup (77-115)
utils/does-custom-group-match.ts (1)
  • doesCustomGroupMatch (121-141)
utils/is-node-eslint-disabled.ts (1)
  • isNodeEslintDisabled (27-32)
utils/range-to-diff.ts (1)
  • rangeToDiff (32-41)
utils/should-partition.ts (1)
  • shouldPartition (69-95)
utils/sort-nodes-by-groups.ts (1)
  • sortNodesByGroups (106-162)
utils/get-custom-groups-compare-options.ts (1)
  • buildGetCustomGroupOverriddenOptionsFunction (131-142)
utils/report-all-errors.ts (1)
  • reportAllErrors (203-325)
utils/report-errors.ts (4)
  • MISSED_SPACING_ERROR (33-34)
  • EXTRA_SPACING_ERROR (30-31)
  • GROUP_ORDER_ERROR (27-28)
  • ORDER_ERROR (21-22)
rules/sort-named-exports/types.ts (5)
rules/sort-named-imports/types.ts (2)
  • Options (47-59)
  • SingleCustomGroup (22-40)
types/common-groups-options.ts (1)
  • CommonGroupsOptions (7-19)
types/common-partition-options.ts (1)
  • CommonPartitionOptions (3-15)
types/common-options.ts (1)
  • CommonOptions (23-73)
types/sorting-node.ts (1)
  • SortingNode (18-102)
rules/sort-modules/types.ts (3)
types/common-groups-options.ts (1)
  • CommonGroupsOptions (7-19)
types/common-partition-options.ts (1)
  • CommonPartitionOptions (3-15)
types/common-options.ts (1)
  • CommonOptions (23-73)
rules/sort-object-types/types.ts (4)
types/common-options.ts (4)
  • RegexOption (464-464)
  • CustomGroupsOption (103-134)
  • FallbackSortOption (301-313)
  • CommonOptions (23-73)
types/common-groups-options.ts (1)
  • CommonGroupsOptions (7-19)
types/common-partition-options.ts (1)
  • CommonPartitionOptions (3-15)
types/join-with-dash.ts (1)
  • JoinWithDash (4-4)
rules/sort-objects/types.ts (3)
types/common-options.ts (2)
  • RegexOption (464-464)
  • CommonOptions (23-73)
types/common-groups-options.ts (1)
  • CommonGroupsOptions (7-19)
types/common-partition-options.ts (1)
  • CommonPartitionOptions (3-15)
rules/sort-classes/types.ts (3)
types/common-options.ts (2)
  • RegexOption (464-464)
  • CommonOptions (23-73)
types/common-groups-options.ts (1)
  • CommonGroupsOptions (7-19)
types/common-partition-options.ts (1)
  • CommonPartitionOptions (3-15)
rules/sort-union-types/types.ts (3)
types/common-groups-options.ts (1)
  • CommonGroupsOptions (7-19)
types/common-partition-options.ts (1)
  • CommonPartitionOptions (3-15)
types/common-options.ts (1)
  • CommonOptions (23-73)
rules/sort-variable-declarations/types.ts (3)
types/common-groups-options.ts (1)
  • CommonGroupsOptions (7-19)
types/common-partition-options.ts (1)
  • CommonPartitionOptions (3-15)
types/common-options.ts (1)
  • CommonOptions (23-73)
rules/sort-exports/types.ts (3)
types/common-groups-options.ts (1)
  • CommonGroupsOptions (7-19)
types/common-partition-options.ts (1)
  • CommonPartitionOptions (3-15)
types/common-options.ts (1)
  • CommonOptions (23-73)
rules/sort-jsx-props/types.ts (4)
rules/sort-array-includes/types.ts (2)
  • Options (19-35)
  • SingleCustomGroup (49-61)
types/common-options.ts (2)
  • RegexOption (464-464)
  • CommonOptions (23-73)
types/common-partition-options.ts (1)
  • CommonPartitionOptions (3-15)
types/common-groups-options.ts (1)
  • CommonGroupsOptions (7-19)
rules/sort-named-imports/types.ts (4)
types/common-groups-options.ts (1)
  • CommonGroupsOptions (7-19)
types/common-partition-options.ts (1)
  • CommonPartitionOptions (3-15)
types/common-options.ts (1)
  • CommonOptions (23-73)
types/sorting-node.ts (1)
  • SortingNode (18-102)
🔇 Additional comments (35)
rules/sort-variable-declarations/types.ts (2)

3-5: Imports of shared option types look correct and consistent

Bringing in CommonPartitionOptions, CommonOptions, RegexOption, and CommonGroupsOptions aligns this rule with the shared option abstractions used elsewhere; the types line up with their definitions and are appropriate for the new composite Options type.


31-41: The implementation is correct; suggested refactoring conflicts with codebase patterns

The array-based Options type is correctly implemented throughout: tests use options: [{}], the rule accesses it via context.options.at(0), and defaultOptions is properly typed as Required<Options[number]>. No remaining assumptions of a single options object exist.

However, the review's suggestions conflict with established codebase patterns:

  • allSelectors as const: All other rules in the codebase (sort-object-types, sort-union-types, sort-named-imports, sort-objects, sort-modules, sort-named-exports) use export let allSelectors, not const. Changing this would introduce inconsistency.
  • Named alias extraction: While cosmetic and clean, this is optional and not required for correctness or readability—the inline intersection is transparent and mirrors the inline structure already present in other shared option types.
docs/content/rules/sort-jsx-props.mdx (4)

318-330: Groups/newlines option docs now match the new groups surface.

The updated groups union (string, string[], { newlinesBetween }, and { group, type?, order? }) plus the dedicated “Newlines between groups” section correctly describe per‑group overrides and boundary newlines behavior, in line with the shared CommonGroupsOptions design. No issues here.

Also applies to: 373-390


488-502: Callback custom group example is clear and matches the new customGroups API.

The example correctly shows adding 'callback' to groups and defining a matching customGroups entry with groupName: 'callback' and elementNamePattern: '^on.+'; this is a good, realistic illustration of per‑group customization.


532-533: Default customGroups updated to array form.

Switching the usage examples from customGroups: {} to customGroups: [] aligns the docs with the new Array<CustomGroupDefinition | CustomGroupAnyOfDefinition> API and the migration note above. This should avoid confusion for users copying the default config.

Also applies to: 562-563


582-584: Updated test source link looks consistent with repo layout.

The “Test source” link now points at test/rules/sort-jsx-props.test.ts, which matches the rest of the project’s test references; as long as the Vitest migration kept this path, the link is correct.

rules/sort-jsx-props/types.ts (1)

3-5: Options/Group wiring now consistently uses shared Common types.*

The refactored Options type (conditional useConfigurationIf, Pick<CommonPartitionOptions, 'partitionByNewLine'>, CommonGroupsOptions<Group, SingleCustomGroup>, and CommonOptions) plus the simplified Group alias and allSelectors = ['prop'] match the shared pattern used by other sorting rules and the public docs. The type surface looks coherent and type-safe for the rule’s configuration.

Also applies to: 54-82, 108-108, 123-123

docs/content/rules/sort-maps.mdx (2)

276-288: Groups option type and per‑group overrides docs look consistent with new API

The expanded groups union type and the “Group with overridden settings” section accurately describe the array/override semantics (string, string[], { newlinesBetween }, and { group, type, order }) and match the CommonGroupsOptions shape used in code. This should give users enough detail to configure per‑group sort behavior and unsorted groups.

Also applies to: 302-316


475-475: Updated test link path

The Test source link now points at test/rules/sort-maps.test.ts, which matches the new test layout used elsewhere in the PR.

rules/sort-array-includes/types.ts (1)

3-5: Options refactor to shared Common option blocks looks sound*

Composing Options from CommonGroupsOptions<Group, SingleCustomGroup>, CommonPartitionOptions, and CommonOptions (plus the rule‑specific useConfigurationIf) is consistent with the new shared option model across rules and should keep this rule aligned with the common JSON‑schema/typing story. The Group = 'unknown' | string alias remains compatible with CommonGroupsOptionsGroup extends string constraint, and RegexOption is correctly reused for allNamesMatchPattern.

Please run the TypeScript build or type‑check to ensure all downstream imports of Options and the JSON‑schema builder for this rule still type‑check cleanly with the new composition.

Also applies to: 32-34

docs/content/rules/sort-variable-declarations.mdx (3)

219-231: Groups union and per‑group override docs align with shared groups API

The updated groups type union and the “Group with overridden settings” section correctly mirror the new CommonGroupsOptions shape (string, string[], { newlinesBetween }, and { group, type?, order? }). The example using 'initialized' and { group: 'uninitialized', type: 'unsorted' } clearly shows how to disable sorting for a specific group while preserving global behavior elsewhere.

Also applies to: 252-266


294-294: Clarified customGroups description

The change to “match specific variable declaration members” better reflects this rule’s domain and avoids confusion with object‑type members.


426-426: Test link path update

Pointing the Test source link to test/rules/sort-variable-declarations.test.ts matches the reorganized test tree and keeps docs in sync with the repository.

rules/sort-maps/types.ts (1)

3-5: Options composition matches shared configuration model

Refactoring Options to be Partial<{ useConfigurationIf: ... } & CommonGroupsOptions<Group, SingleCustomGroup> & CommonPartitionOptions & CommonOptions>[] cleanly aligns this rule with the shared option blocks used elsewhere. The dedicated SingleCustomGroup interface and singleCustomGroupJsonSchema for elementNamePattern match the documented customGroups shape for maps, and RegexOption is reused appropriately for allNamesMatchPattern.

It would be good to re‑run the type‑checker and ensure the JSON‑schema builder and rule implementation for sort-maps (especially where Options[number] is used) still compile against this updated type.

Also applies to: 28-30

docs/content/rules/sort-object-types.mdx (5)

287-289: New useConfigurationIf filters are well documented

Adding declarationCommentMatchesPattern and hasNumericKeysOnly to useConfigurationIf and documenting their behavior (including the limitation to unquoted numeric literal keys) gives users fine‑grained control over when configurations apply. The examples for declarationCommentMatchesPattern: '^do not sort$' and hasNumericKeysOnly: true clearly demonstrate realistic use cases.

Also applies to: 352-376, 378-393


307-320: RGB customGroups example matches the new array-based API

The updated customGroups example using an array of { groupName, elementNamePattern } objects is consistent with the new array‑based customGroups option and clearly shows how to map r, g, and b keys into dedicated groups alongside the groups: ['r', 'g', 'b'] configuration.


398-410: Groups union and per‑group overrides section align with shared groups semantics

The expanded groups type union and accompanying examples (“Group with overridden settings”) correctly describe the supported entries (selectors as strings, combined groups as string[], { newlinesBetween } separators, and { group, type?, order? } overrides). The example that makes multiline-member unsorted illustrates the override behavior well and is consistent with how other rules’ docs now present group‑level overrides.

Also applies to: 444-453, 524-538


678-696: Combined groups and customGroups “top/unknown/bottom” example is clear

The configuration showing groups: ['top', 'unknown', ['optional-multiline-member', 'bottom']] plus matching customGroups for top and bottom nicely demonstrates combining multiple groups and driving them via selector/pattern‑based custom groups. This should help users reason about more advanced grouping setups.


784-784: Test link path in Resources updated correctly

Linking to test/rules/sort-object-types.test.ts matches the new test file layout and keeps the documentation’s “Test source” reference accurate.

rules/sort-union-types/types.ts (1)

3-5: Options refactor cleanly composes shared Common option types*

The new imports and Options alias (Partial<CommonGroupsOptions<Group, SingleCustomGroup> & CommonPartitionOptions & CommonOptions>[]) look correct and consistent with other rules; no issues from a type-soundness or API-shape perspective.

Also applies to: 51-60

rules/sort-named-exports/types.ts (1)

4-6: Named-exports Options and sorting-node alias look consistent with the new shared pattern

The Options refactor (array of Partial<{ ignoreAlias } & CommonGroupsOptions<Group, SingleCustomGroup> & CommonPartitionOptions & CommonOptions>) and the SortNamedExportsSortingNode = SortingNode<TSESTree.ExportSpecifier> alias both look coherent and in line with the other sorting rules’ API shapes. Please just ensure the rule implementation and tests now operate on ExportSpecifier nodes rather than the previous declaration-level shape.

Also applies to: 43-59, 61-62

rules/sort-classes/types.ts (1)

3-5: SortClassesOptions now cleanly composes shared Common options*

The updated SortClassesOptions tuple, intersecting { ignoreCallbackDependenciesPatterns } with CommonGroupsOptions<Group, SingleCustomGroup>, CommonPartitionOptions, and CommonOptions, is type-sound and matches the shared configuration model adopted elsewhere; no changes needed.

Also applies to: 32-51

rules/sort-named-imports/types.ts (1)

4-6: Named-imports Options and sorting-node alias are aligned with the shared config model

The new Options alias (array of Partial<{ ignoreAlias } & CommonGroupsOptions<Group, SingleCustomGroup> & CommonPartitionOptions & CommonOptions>) and SortNamedImportsSortingNode = SortingNode<TSESTree.ImportClause> look correct and consistent with other rules. Please confirm the rule implementation and tests are updated to work with ImportClause-based sorting nodes.

Also applies to: 42-59, 61-62

rules/sort-object-types/types.ts (1)

10-11: Options refactor for sort-object-types correctly specializes Common options*

The Options type now cleanly combines rule-specific fields (useConfigurationIf, specialized customGroups, specialized fallbackSort, sortBy) with shared behavior by intersecting Omit<CommonGroupsOptions<Group, SingleCustomGroup>, 'customGroups'>, Omit<CommonOptions, 'fallbackSort'>, and CommonPartitionOptions. The additional declarationCommentMatchesPattern? and hasNumericKeysOnly? flags, plus the enriched customGroups/fallbackSort shapes using CustomGroupsOption<SingleCustomGroup, { fallbackSort?: { sortBy?: 'value' | 'name' } & FallbackSortOption }>, all look type-safe and aligned with the intended configuration semantics.

Also applies to: 27-39, 52-67, 72-86

rules/sort-object-types/build-node-value-getter.ts (1)

15-23: LGTM! Enhanced exhaustiveness checking.

The switch statement provides better compile-time type safety compared to a ternary. The UnreachableCaseError in the default case ensures exhaustive handling of all sortBy variants.

rules/sort-imports/types.ts (1)

181-185: LGTM! New modifiers properly integrated.

The singleline and multiline modifiers are correctly defined and integrated into the allModifiers array.

docs/content/rules/sort-union-types.mdx (1)

235-247: LGTM! Well-documented per-group override feature.

The expanded groups type definition clearly documents the new per-group override capabilities, allowing fine-grained control over sorting behavior for specific groups.

docs/content/rules/sort-enums.mdx (1)

173-179: LGTM! Clear documentation of sortByValue options.

The documentation correctly explains the three-value sortByValue option and its behavior for each setting.

docs/content/rules/sort-named-exports.mdx (1)

253-265: LGTM! Consistent documentation structure.

The groups option documentation follows the same clear pattern as other rules in this PR, making the codebase documentation more consistent.

docs/content/rules/sort-classes.mdx (1)

327-339: LGTM! Comprehensive groups option documentation.

The updated type definition clearly shows all the flexible configuration options available for the groups array, including per-group overrides and newline control.

rules/sort-exports/types.ts (1)

3-6: Options type composition looks consistent with shared option infrastructure

The Options alias cleanly composes CommonGroupsOptions<Group, SingleCustomGroup>, CommonPartitionOptions, and CommonOptions and matches the patterns used in other rules. No issues from this file alone; it should integrate smoothly with the rule implementation.

Please double-check that rules/sort-exports.ts treats Options consistently (e.g., how it pulls Options[0] vs. the options array) in the same way as other refactored sorting rules.

Also applies to: 48-58

rules/sort-objects/types.ts (1)

3-5: New Options / selector wiring for sort-objects looks coherent

The extended Options (with useConfigurationIf fields and composition of CommonGroupsOptions, CommonPartitionOptions, and CommonOptions) plus the updated Selector/Group/allSelectors wiring all look internally consistent and compatible with the shared helpers.

Please confirm that:

  • The docs for sort-objects list the new useConfigurationIf fields (objectType, declarationCommentMatchesPattern, declarationMatchesPattern, hasNumericKeysOnly), and
  • The rule implementation applies them as intended.

Also applies to: 20-63, 78-81, 115-122, 205-205, 257-257

rules/sort-import-attributes/types.ts (1)

1-47: Types and schema look consistent with existing attribute rules.

The SingleCustomGroup, Group, Options, and singleCustomGroupJsonSchema definitions align with the shared Common* option patterns and the sort-export-attributes types, so the new rule surface looks coherent and type‑safe.

rules/sort-modules/types.ts (1)

3-55: Refactored SortModulesOptions correctly composes shared option types.

Using CommonGroupsOptions<Group, SingleCustomGroup> & CommonPartitionOptions & CommonOptions inside the single‑element tuple keeps the ESLint [options] shape while aligning with the new common option model; this looks sound.

test/rules/sort-array-includes.test.ts (1)

840-871: LGTM! Well-structured test for per-group option overrides.

This test correctly validates the new per-group override feature, ensuring that group-specific type and order settings override global configuration.

{
type: 'unsorted', // Do not sort metadata objects
useConfigurationIf: {
declarationMatchesPattern: '*metadata$',
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Clarify pattern syntax for declarationMatchesPattern.

The example shows declarationMatchesPattern: '*metadata$' which mixes glob-like (*) and regex-like ($) syntax. Based on the type definition on line 310 showing it accepts regex patterns, this should likely be '.*metadata$' or 'metadata$' to be valid regex.

Apply this diff if regex is intended:

-        declarationMatchesPattern: '*metadata$',
+        declarationMatchesPattern: '.*metadata$',
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
declarationMatchesPattern: '*metadata$',
declarationMatchesPattern: '.*metadata$',
🤖 Prompt for AI Agents
In docs/content/rules/sort-objects.mdx around line 387, the example uses a mixed
glob/regex pattern `*metadata$` which is invalid for a regex-based field; update
the value to a valid regex such as `'.*metadata$'` (or `'metadata$'` if only
suffix match is desired) so it matches the intended metadata suffix and conforms
to the type definition.

Comment on lines +11 to +25
export type Options = Partial<
{
sortOnParameters: boolean
sortOnProperties: boolean
sortOnAccessors: boolean
sortOnMethods: boolean
sortOnClasses: boolean
} & CommonGroupsOptions<Group, SingleCustomGroup> &
CommonPartitionOptions &
CommonOptions
>[]

export interface SingleCustomGroup {
elementNamePattern?: RegexOption
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

SingleCustomGroup is missing groupName, which breaks typed customGroups and schema alignment.

Every other rule’s SingleCustomGroup (e.g. sort-export-attributes) exposes a groupName: string so that customGroups entries can be named and referenced from groups. Here it’s omitted from both the TypeScript interface and the singleCustomGroupJsonSchema, which means:

  • TS configs using customGroups: [{ groupName: 'myGroup', ... }] will fail excess‑property checks against SingleCustomGroup.
  • The JSON schema won’t validate or even describe the groupName field for this rule’s custom groups.

To align with the shared customGroups model and avoid surprising TS/schema behavior, consider:

 export type Options = Partial<
   {
     sortOnParameters: boolean
     sortOnProperties: boolean
     sortOnAccessors: boolean
     sortOnMethods: boolean
     sortOnClasses: boolean
   } & CommonGroupsOptions<Group, SingleCustomGroup> &
     CommonPartitionOptions &
     CommonOptions
 >[]

 export interface SingleCustomGroup {
-  elementNamePattern?: RegexOption
+  /** Name of the custom group, referenced from the `groups` option. */
+  groupName: string
+
+  /** Pattern used to match decorator names for this custom group. */
+  elementNamePattern?: RegexOption
 }

 type Group = 'unknown' | string

 export let singleCustomGroupJsonSchema: Record<string, JSONSchema4> = {
-  elementNamePattern: regexJsonSchema,
+  groupName: { type: 'string' },
+  elementNamePattern: regexJsonSchema,
 }

This mirrors the other rules’ custom-group surfaces and keeps TS types and JSON schema consistent.

Also applies to: 31-33

🤖 Prompt for AI Agents
In rules/sort-decorators/types.ts around lines 11 to 25, the SingleCustomGroup
type lacks groupName which breaks typed customGroups and the JSON schema; add a
groupName: string field to the SingleCustomGroup interface and update the
corresponding singleCustomGroupJsonSchema to include a groupName property (type:
"string") and mark it required if other rules require it, and make the same
change where SingleCustomGroup is duplicated around lines 31-33 so TypeScript
types and schema align with other rules.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 5

♻️ Duplicate comments (8)
docs/content/rules/sort-heritage-clauses.mdx (1)

148-159: Fix terminology: replace "class decorators" with "heritage clauses".

The existing comment flag from the prior review still applies here. This rule concerns extends/implements clauses, not decorators.

- Enables the use of comments to separate class decorators into logical groups.
+ Enables the use of comments to separate heritage clauses into logical groups.
docs/content/rules/sort-modules.mdx (1)

519-519: Fix syntax error: remove trailing periods

The elementNamePattern values have trailing periods, making the TypeScript code invalid.

Apply this diff:

-            elementNamePattern: 'Input'.
+            elementNamePattern: 'Input'

Apply the same fix on both lines 519 and 523.

Also applies to: 523-523

test/rules/sort-export-attributes.test.ts (2)

25-25: Fix test title: "import" → "export"

This test validates export attribute sorting, not import attributes.


50-50: Fix additional test titles: "import" → "export"

These test descriptions incorrectly reference "import attributes" when they validate export attribute sorting.

Update the following lines:

  • Line 50: "sorts multiline import attributes" → "sorts multiline export attributes"
  • Line 323: "sorts import attributes" → "sorts export attributes"
  • Line 348: "sorts multiline import attributes" → "sorts multiline export attributes"
  • Line 598: "sorts import attributes" → "sorts export attributes"
  • Line 623: "sorts multiline import attributes" → "sorts multiline export attributes"
  • Line 878: "sorts import attributes using custom alphabet" → "sorts export attributes using custom alphabet"

Also applies to: 323-323, 348-348, 598-598, 623-623, 878-878

docs/content/rules/sort-objects.mdx (1)

387-387: Fix pattern syntax: use valid regex

The pattern '*metadata$' mixes glob-like (*) and regex-like ($) syntax. For a regex pattern, use '.*metadata$' or 'metadata$'.

Apply this diff:

-        declarationMatchesPattern: '*metadata$',
+        declarationMatchesPattern: '.*metadata$',
docs/content/rules/sort-decorators.mdx (1)

382-389: Correct CustomGroupDefinition typings for consistency

The fallbackSort.type field uses string instead of the proper union type used elsewhere in this file (lines 145-150). For consistency, use the same type union.

Apply this diff:

 interface CustomGroupDefinition {
   groupName: string
   type?: 'alphabetical' | 'natural' | 'line-length' | 'unsorted'
   order?: 'asc' | 'desc'
-  fallbackSort?: { type: string; order?: 'asc' | 'desc' }
+  fallbackSort?: {
+    type: 'alphabetical' | 'natural' | 'line-length' | 'custom' | 'unsorted'
+    order?: 'asc' | 'desc'
+  }
   newlinesInside?: number
   elementNamePattern?: string | string[] | { pattern: string; flags?: string } | { pattern: string; flags?: string }[]
 }

Note: The past review also suggested changing newlinesInside to 'always' | 'never' | number, but I cannot verify this is correct from the provided context. Verify against the actual type definitions.

docs/content/rules/sort-jsx-props.mdx (1)

269-287: Fix the RGB regex anchoring in the example configuration

allNamesMatchPattern: '^r|g|b$' is parsed as (^r) or g or (b$), so it will also match names that merely contain g or end with b. Wrap the alternatives in a single anchored group so only exact "r", "g", or "b" match:

-      useConfigurationIf: {
-        allNamesMatchPattern: '^r|g|b$',
-      },
+      useConfigurationIf: {
+        allNamesMatchPattern: '^(?:r|g|b)$',
+      },
docs/content/rules/sort-interfaces.mdx (1)

539-547: Make the “Example 2” interface snippet syntactically complete

The Interface example ends with method(): string but never closes the interface before the code fence. This makes the sample invalid TypeScript and was already called out earlier. Consider adding the missing }:

 interface Interface {
   // 'index-signature'
   [key: string]: any;
   // 'optional-property'
   description?: string;
   // 'required-method'
   method(): string
-```
+}
+```
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f9919cb and 885b3a8.

📒 Files selected for processing (26)
  • docs/content/rules/sort-array-includes.mdx (5 hunks)
  • docs/content/rules/sort-classes.mdx (4 hunks)
  • docs/content/rules/sort-decorators.mdx (6 hunks)
  • docs/content/rules/sort-enums.mdx (6 hunks)
  • docs/content/rules/sort-export-attributes.mdx (1 hunks)
  • docs/content/rules/sort-exports.mdx (4 hunks)
  • docs/content/rules/sort-heritage-clauses.mdx (6 hunks)
  • docs/content/rules/sort-import-attributes.mdx (1 hunks)
  • docs/content/rules/sort-imports.mdx (6 hunks)
  • docs/content/rules/sort-interfaces.mdx (8 hunks)
  • docs/content/rules/sort-intersection-types.mdx (6 hunks)
  • docs/content/rules/sort-jsx-props.mdx (7 hunks)
  • docs/content/rules/sort-maps.mdx (3 hunks)
  • docs/content/rules/sort-modules.mdx (4 hunks)
  • docs/content/rules/sort-named-exports.mdx (3 hunks)
  • docs/content/rules/sort-named-imports.mdx (3 hunks)
  • docs/content/rules/sort-object-types.mdx (8 hunks)
  • docs/content/rules/sort-objects.mdx (9 hunks)
  • docs/content/rules/sort-sets.mdx (5 hunks)
  • docs/content/rules/sort-union-types.mdx (5 hunks)
  • docs/content/rules/sort-variable-declarations.mdx (4 hunks)
  • test/rules/sort-array-includes.test.ts (42 hunks)
  • test/rules/sort-classes.test.ts (27 hunks)
  • test/rules/sort-decorators.test.ts (3 hunks)
  • test/rules/sort-enums.test.ts (41 hunks)
  • test/rules/sort-export-attributes.test.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (6)
  • docs/content/rules/sort-maps.mdx
  • test/rules/sort-classes.test.ts
  • docs/content/rules/sort-import-attributes.mdx
  • docs/content/rules/sort-export-attributes.mdx
  • docs/content/rules/sort-classes.mdx
  • docs/content/rules/sort-intersection-types.mdx
🧰 Additional context used
🧬 Code graph analysis (1)
test/rules/sort-export-attributes.test.ts (2)
utils/alphabet.ts (1)
  • Alphabet (46-467)
test/utils/validate-rule-json-schema.ts (1)
  • validateRuleJsonSchema (8-19)
🔇 Additional comments (31)
docs/content/rules/sort-named-imports.mdx (3)

252-265: LGTM!

The expanded Groups type definition correctly documents the new per-group override capabilities.


299-314: LGTM!

The "Group with overridden settings" section clearly documents the new per-group override feature.


476-476: LGTM!

Test source link correctly updated to the new path.

docs/content/rules/sort-modules.mdx (1)

690-690: LGTM!

Test source link correctly points to the new path structure.

docs/content/rules/sort-object-types.mdx (3)

287-289: LGTM!

New useConfigurationIf options are well-documented with clear examples.

Also applies to: 352-393


398-411: LGTM!

Groups type definition correctly reflects the expanded API with per-group overrides.


525-540: LGTM!

Clear documentation of the per-group override feature.

docs/content/rules/sort-variable-declarations.mdx (2)

219-232: LGTM!

Groups type and per-group overrides are well-documented and consistent with other rules.

Also applies to: 253-268


296-296: LGTM!

Correctly updated terminology to match the rule's purpose (variable declarations, not object type members).

docs/content/rules/sort-objects.mdx (1)

463-476: LGTM!

Groups type definition and per-group overrides are well-documented.

Also applies to: 565-580

docs/content/rules/sort-imports.mdx (2)

288-302: LGTM!

Groups type definition, per-group overrides, and newlines between groups are thoroughly documented.

Also applies to: 454-495


362-363: LGTM!

New multiline and singleline modifiers are properly documented.

docs/content/rules/sort-decorators.mdx (2)

247-268: LGTM!

New partitionByNewLine, newlinesBetween options, and per-group overrides are well-documented.

Also applies to: 273-286, 306-340


549-549: LGTM!

Test source link correctly updated to the new path.

docs/content/rules/sort-union-types.mdx (1)

368-383: Documentation is clear and well-structured.

The new "Group with overridden settings" section effectively explains per-group overrides for type, order, and newlinesInside. The example demonstrates the feature well.

docs/content/rules/sort-enums.mdx (2)

173-179: sortByValue documentation is correct.

The option is now properly documented as a string enum with three values ('always', 'never', 'ifNumericEnum') rather than a boolean, addressing the previous review feedback.


263-278: Group override documentation is clear and consistent.

The "Group with overridden settings" section matches the pattern used in sort-union-types.mdx, maintaining consistency across rule documentation.

test/rules/sort-decorators.test.ts (3)

554-641: Excellent use of parameterized testing.

The it.each approach for testing different elementNamePattern formats (string, array, case-insensitive regex, regex in array) is a best practice that reduces code duplication while ensuring comprehensive coverage.


935-1290: Comprehensive newline behavior testing.

The extensive test coverage for newlinesBetween with various values (0, 1, 'ignore') and their interactions with global vs. group-level settings ensures the complex newline logic is well-validated. The parameterized tests effectively cover the matrix of scenarios.


1334-1378: Good edge case coverage for partition boundaries.

The test correctly verifies that partition boundaries are preserved even when newlinesBetween: 0 is set, which is an important edge case that could easily be overlooked.

test/rules/sort-enums.test.ts (4)

70-74: Verify the intent behind numeric key quoting.

The numeric enum keys have been changed from unquoted to single-quoted strings (e.g., '1', '12', '2', '8'). This appears intentional and consistent across all test sections, but please confirm this aligns with how the rule now handles numeric enum keys.

If this change reflects updated behavior in how enum keys are normalized or compared, consider documenting this in the rule's documentation or changelog.

Also applies to: 91-95, 100-103


652-656: LGTM: sortByValue API evolution is well-tested.

The change from a boolean sortByValue option to a string union ('always' | 'never' | 'ifNumericEnum') improves API clarity and provides more granular control. The test coverage for all three values is comprehensive.

Since this is a breaking change for v5.0.0, ensure it's clearly documented in the migration guide.

Also applies to: 658-674


775-820: LGTM: Per-group override test is comprehensive.

The new test validates that group-level overrides (type, order, newlinesInside) work correctly, covering both sorting and spacing enforcement. This aligns well with the PR's objective to add per-group configuration capabilities.


1172-1295: LGTM: Comprehensive newlinesBetween test coverage.

The new tests thoroughly validate the newlinesBetween option behavior:

  • Value 0 removes all newlines between groups
  • Value 1 enforces exactly one newline
  • Proper error messages for extraSpacingBetweenEnumsMembers and missedSpacingBetweenEnumsMembers

The migration from string values like 'always' to numeric values (1) improves API clarity.

Also applies to: 1327-1343

docs/content/rules/sort-array-includes.mdx (2)

312-327: LGTM: groups option type expansion is well-documented.

The expanded groups type definition provides comprehensive support for per-group configuration, including:

  • Simple string/array grouping
  • Per-group newline controls (newlinesBetween)
  • Per-group sort overrides (type, order, newlinesInside)

The default change from [] to ['literal'] is a sensible improvement that provides better out-of-the-box behavior.

Ensure this default change is highlighted in the migration guide for v5.0.0.


346-362: LGTM: Clear documentation for per-group overrides.

The new "Group with overridden settings" section provides clear, practical examples of how to use per-group configuration. The example showing { group: 'spread', type: 'unsorted' } effectively demonstrates the feature.

docs/content/rules/sort-exports.mdx (2)

264-286: LGTM: commentAbove feature is well-documented.

The commentAbove feature for sort-exports is clearly explained, including:

  • Purpose: Enforce presence of specific comments above group top elements
  • Auto-fixing: Automatically adds missing comments
  • Auto-removal: Removes invalid auto-added comments

The documentation appropriately warns users about the auto-removal behavior.


288-305: LGTM: Newlines between groups documentation is clear.

The "Newlines between groups" section effectively explains how to use newlinesBetween objects within the groups array to override the global setting between specific groups. The prerequisite note about partitionByNewLine is helpful.

docs/content/rules/sort-sets.mdx (2)

271-286: LGTM: Documentation is consistent and terminology is clear.

The groups type definition and default value changes are consistent with other rules in the PR. The terminology has been appropriately updated to refer to "Set elements" rather than generic elements, improving clarity.

Also applies to: 302-303


305-320: LGTM: Per-group override documentation is consistent.

The "Group with overridden settings" section follows the same clear pattern established in other rule documentation files. The example appropriately demonstrates how to disable sorting for the spread group.

test/rules/sort-array-includes.test.ts (1)

1351-1411: New newline/group-override tests look internally consistent

The added cases around newlinesBetween (global vs per-group overrides, including 0, 1, 2, and 'ignore') and partition preservation exercise the edge semantics well; inputs, outputs, and expected errors payloads all line up with the described behavior, and option shapes match the rule’s public API. No issues from a test-logic perspective.

Also applies to: 1584-1637, 3124-3184, 3357-3410, 4878-4937, 5111-5164

Comment on lines +295 to +302
interface CustomGroupDefinition {
groupName: string
type?: 'alphabetical' | 'natural' | 'line-length' | 'unsorted'
order?: 'asc' | 'desc'
fallbackSort?: { type: string; order?: 'asc' | 'desc' }
newlinesInside?: number
elementNamePattern?: string | string[] | { pattern: string; flags?: string } | { pattern: string; flags?: string }[]
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Add 'custom' to type unions in CustomGroupDefinition and CustomGroupAnyOfDefinition.

The type option at line 194 (within the groups section) explicitly includes 'custom' as a valid type. However, both custom group definition interfaces are missing 'custom' from their type unions. This inconsistency creates confusion about which sorting types are actually supported in custom groups.

  interface CustomGroupDefinition {
    groupName: string
-   type?: 'alphabetical' | 'natural' | 'line-length' | 'unsorted'
+   type?: 'alphabetical' | 'natural' | 'line-length' | 'custom' | 'unsorted'
    order?: 'asc' | 'desc'
    fallbackSort?: { type: string; order?: 'asc' | 'desc' }
    newlinesInside?: number
    elementNamePattern?: string | string[] | { pattern: string; flags?: string } | { pattern: string; flags?: string }[]
  }
  interface CustomGroupAnyOfDefinition {
    groupName: string
-   type?: 'alphabetical' | 'natural' | 'line-length' | 'unsorted'
+   type?: 'alphabetical' | 'natural' | 'line-length' | 'custom' | 'unsorted'
    order?: 'asc' | 'desc'
    fallbackSort?: { type: string; order?: 'asc' | 'desc' }
    newlinesInside?: number
    anyOf: Array<{
        selector?: string
        elementNamePattern?: string | string[] | { pattern: string; flags?: string } | { pattern: string; flags?: string }[]
    }>
  }

Also applies to: 310-320

🤖 Prompt for AI Agents
In docs/content/rules/sort-heritage-clauses.mdx around lines 295-302 (and
similarly around 310-320), the CustomGroupDefinition and
CustomGroupAnyOfDefinition interfaces list type unions that omit the 'custom'
option; update both interfaces to include 'custom' in their type unions so the
docs reflect that custom groups accept type: 'custom' (ensure the union string
list includes 'custom' alongside 'alphabetical' | 'natural' | 'line-length' |
'unsorted').

Comment on lines 330 to 347
groups: ['r', 'g', 'b'], // Sort colors types by RGB
customGroups: {
r: '^r$',
g: '^g$',
b: '^b$',
},
customGroups: [
{
groupName: 'r',
elementNamePattern: '^r$',
},
{
groupName: 'g',
elementNamePattern: '^g$',
},
{
groupName: 'b',
elementNamePattern: '^b$',
},
],
useConfigurationIf: {
allNamesMatchPattern: '^r|g|b$',
},
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Correct the RGB regex anchoring in this example

Here too, allNamesMatchPattern: '^r|g|b$' matches unintended names (g, words ending with b, etc.). To restrict it to interfaces whose keys are exactly "r", "g", or "b", wrap the alternation:

-      useConfigurationIf: {
-        allNamesMatchPattern: '^r|g|b$',
-      },
+      useConfigurationIf: {
+        allNamesMatchPattern: '^(?:r|g|b)$',
+      },
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
groups: ['r', 'g', 'b'], // Sort colors types by RGB
customGroups: {
r: '^r$',
g: '^g$',
b: '^b$',
},
customGroups: [
{
groupName: 'r',
elementNamePattern: '^r$',
},
{
groupName: 'g',
elementNamePattern: '^g$',
},
{
groupName: 'b',
elementNamePattern: '^b$',
},
],
useConfigurationIf: {
allNamesMatchPattern: '^r|g|b$',
},
groups: ['r', 'g', 'b'], // Sort colors types by RGB
customGroups: [
{
groupName: 'r',
elementNamePattern: '^r$',
},
{
groupName: 'g',
elementNamePattern: '^g$',
},
{
groupName: 'b',
elementNamePattern: '^b$',
},
],
useConfigurationIf: {
allNamesMatchPattern: '^(?:r|g|b)$',
},
🤖 Prompt for AI Agents
In docs/content/rules/sort-interfaces.mdx around lines 330 to 347, the example
uses the regex allNamesMatchPattern: '^r|g|b$' which incorrectly anchors only
the first alternative and therefore matches unintended names; update the pattern
so the alternation is grouped and the anchors apply to the whole expression (for
example use '^(?:r|g|b)$' or '^(r|g|b)$') so only exact keys "r", "g", or "b"
match.

Comment on lines 389 to +435
<sub>
type: `Array<string | string[]>`
type:
```ts
Array<
| string
| string[]
| { newlinesBetween: number }
| {
group: string | string[];
type?: 'alphabetical' | 'natural' | 'line-length' | 'custom' | 'unsorted';
order?: 'asc' | 'desc';
newlinesInside?: number;
}
>
```
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Align groupsnewlinesBetween override type with the global option

The groups type only documents { newlinesBetween: number }, while the global newlinesBetween option supports number | 'ignore'. If group-level newlinesBetween accepts the same values (as it appears to across the sorting rules), it would be clearer to document that here as well so consumers don’t assume numbers are the only valid overrides.

Also applies to: 566-583

🤖 Prompt for AI Agents
In docs/content/rules/sort-interfaces.mdx around lines 421-435 (also apply same
change for lines 566-583), the group-level type for newlinesBetween is
documented as only `{ newlinesBetween: number }` but the global option allows
`number | 'ignore'`; update the docblocks and code examples to accept `{
newlinesBetween: number | 'ignore' }` (and any array/union variants where group
overrides appear) so group-level newlinesBetween matches the global option;
ensure both occurrences at the two ranges are updated consistently.

Comment on lines +318 to +331
type:
```ts
Array<
| string
| string[]
| { newlinesBetween: number }
| {
group: string | string[];
type?: 'alphabetical' | 'natural' | 'line-length' | 'custom' | 'unsorted';
order?: 'asc' | 'desc';
newlinesInside?: number;
}
>
```
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Document per-group newlinesBetween as accepting all supported values

The groups type currently documents { newlinesBetween: number }, but the global newlinesBetween option supports both numbers and 'ignore'. If group-level overrides are meant to mirror the same value space (as suggested by tests in other rules), consider updating the type and examples here to reflect number | 'ignore' so docs accurately describe the full API.

Also applies to: 375-392

🤖 Prompt for AI Agents
In docs/content/rules/sort-jsx-props.mdx around lines 318-331 (and similarly
update the section at lines 375-392), the per-group option is documented as `{
newlinesBetween: number }` but should accept the same values as the global
`newlinesBetween` (number | 'ignore'); update the type annotation and any
examples to `{ newlinesBetween: number | 'ignore' }` and adjust example usages
to include the 'ignore' variant where appropriate so the docs match the actual
API and tests.

Comment on lines +253 to +266
type:
```ts
Array<
| string
| string[]
| { newlinesBetween: number }
| {
group: string | string[];
type?: 'alphabetical' | 'natural' | 'line-length' | 'custom' | 'unsorted';
order?: 'asc' | 'desc';
newlinesInside?: number;
}
>
```
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Clarify allowable values for per-group newlinesBetween overrides

The groups union documents { newlinesBetween: number }, but the top-level newlinesBetween option accepts number | 'ignore'. If { newlinesBetween: 'ignore' } is valid between specific groups (to match that behavior), it would be good to reflect this in the type snippet and surrounding text so users understand all supported override values.

Also applies to: 317-334

🤖 Prompt for AI Agents
In docs/content/rules/sort-named-exports.mdx around lines 253 to 266 (and
likewise update the similar block at 317-334), the per-group override union
shows `{ newlinesBetween: number }` but the top-level option allows `number |
'ignore'`; update the type snippet and adjacent explanatory text so per-group
overrides accept `newlinesBetween: number | 'ignore'` (or `{ newlinesBetween:
number | 'ignore' }`) and mention that `'ignore'` is valid for per-group
settings to match top-level behavior.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4977783 and 4e03287.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml, !pnpm-lock.yaml
📒 Files selected for processing (1)
  • package.json (3 hunks)
🔇 Additional comments (1)
package.json (1)

14-14: ESM migration and dependency consolidation look solid.

The transition to ESM ("type": "module"), Node.js ≥20 requirement, and unified @typescript-eslint/* package versions at ^8.47.0 are all correctly aligned with the v5.0.0 release objectives. The previous duplicate @typescript-eslint/types issue has been resolved.

Also applies to: 60-60, 83-84, 137-137

"vitest": "^3.2.4"
},
"peerDependencies": {
"eslint": ">=8.45.0"
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Update ESLint peerDependency to v9+ to align with v5.0.0 release.

The PR objectives explicitly state "Drop legacy ESLint v8 support" (EOL September 2024), but the peerDependencies constraint still permits ESLint v8 (>=8.45.0). For a major version bump to v5.0.0, the package should require ESLint v9+ to enforce the breaking change.

Apply this diff to align the constraint with the v5.0.0 release goals:

-    "eslint": ">=8.45.0"
+    "eslint": ">=9.0.0"
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
"eslint": ">=8.45.0"
"eslint": ">=9.0.0"
🤖 Prompt for AI Agents
In package.json at line 134, the peerDependency for "eslint" still allows v8
(">=8.45.0") but the v5.0.0 release drops ESLint v8 support; update the
constraint to require ESLint v9 or higher (e.g., ">=9.0.0" or a semver range
that enforces major version 9+) so the peerDependencies reflect the breaking
change.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (2)
astro.config.ts (2)

59-59: Static-analysis ReDoS warning is a false positive here; optional simplification

The new RegExp(\^${site}/guide$`, 'u')pattern is built from a constantsite` string and results in a simple anchored literal, so there’s no realistic ReDoS or injection risk despite the warning. If you want to make this clearer (and a bit cheaper), you could replace the regex with direct equality:

filter: page => page !== `${site}/guide`,

This keeps the same behavior without dynamic regex construction.


73-75: prefetch.defaultStrategy: 'hover' is conservative; consider touch behavior

Using prefetch: { defaultStrategy: 'hover' } reduces unnecessary prefetching and is good for network friendliness, but on touch‑only devices hover often doesn’t fire, so those users may see fewer prefetched navigations than before. If you want similar behavior on touch, you might consider tap or viewport instead; if not, this is fine as‑is.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4e03287 and 0403705.

📒 Files selected for processing (1)
  • astro.config.ts (2 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
astro.config.ts (1)
docs/utils/shiki-theme.ts (1)
  • colorTheme (3-8)
🪛 ast-grep (0.40.0)
astro.config.ts

[warning] 59-59: Regular expression constructed from variable input detected. This can lead to Regular Expression Denial of Service (ReDoS) attacks if the variable contains malicious patterns. Use libraries like 'recheck' to validate regex safety or use static patterns.
Context: new RegExp(^${site}/guide$, 'u')
Note: [CWE-1333] Inefficient Regular Expression Complexity [REFERENCES]
- https://owasp.org/www-community/attacks/Regular_expression_Denial_of_Service_-_ReDoS
- https://cwe.mitre.org/data/definitions/1333.html

(regexp-from-variable)

🔇 Additional comments (3)
astro.config.ts (3)

31-38: Shiki config reactivation and shared theme usage look good

Re‑enabling markdown.shikiConfig with transformerNotationDiff({ matchAlgorithm: 'v3' }) and the shared colorTheme is consistent and should give you diff highlighting with your custom CSS‑variable theme. No issues from my side here.


58-58: Switch to bare svelte() removes previous custom compiler options

Using plain svelte() simplifies the integration and aligns with the default config for @astrojs/svelte, but it does drop the prior explicit compilerOptions (e.g., custom cssHash, discloseVersion). Just ensure you’re not relying on the old hashing or version‑disclosure behavior in snapshots or styling before merging.


70-70: Enabling experimental.svgo may affect SVG markup shape

Turning on experimental.svgo: true is a nice optimization, but it can change SVG output (ID mangling, attribute ordering, whitespace), which in turn can affect HTML/SVG snapshots or very strict DOM assertions in tests. Worth double‑checking snapshot suites for SVG-heavy pages after this change.

@azat-io
Copy link
Owner Author

azat-io commented Nov 22, 2025

@coderabbitai pause

@coderabbitai
Copy link

coderabbitai bot commented Nov 22, 2025

✅ Actions performed

Reviews paused.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Release: v5.0.0

3 participants