Skip to content

Conversation

azat-io
Copy link
Owner

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

Close #566.

Copy link

coderabbitai bot commented Aug 10, 2025

📝 Walkthrough

Summary by CodeRabbit

  • New Features
    • Added rules: sort-import-attributes and sort-export-attributes.
    • Provided new preset configs exposing all rules, including the new ones.
  • Refactor
    • Migrated to array-based customGroups across rules; removed deprecated groupKind and legacy options.
    • Added grouping/spacing options: partitionByComment, partitionByNewLine, and newlinesBetween.
    • Defaults updated in several rules (e.g., literals grouped by default).
  • Documentation
    • New docs for import/export attributes rules; broad updates reflecting array-based customGroups and new options; removed deprecated sections.
  • Chores
    • Switched package to ESM and updated build to ES module output.
    • Raised Node engine requirement to ^20.0.0 || >=22.0.0.

Walkthrough

Convert repository to ESM (package/type changes, Node >=20), replace deprecated object-based customGroups/groupKind APIs with array-based customGroups + groups, add partition/newline options and per-group overrides, refactor utils/types, expose defaultOptions in rule metadata, and add two new rules: sort-import-attributes and sort-export-attributes (with tests/docs).

Changes

Cohort / File(s) Summary
Package & Build
package.json, vite.config.ts
Switch to ESM ("type":"module"), raise Node engines to ^20/≥22, convert Vite build to ES format, replace __dirnameimport.meta.dirname, remove CJS build hooks.
Plugin surface & configs
index.ts, readme.md, docs/public/llms.txt
Add two new rules to exported rules map and configs; update README and public link list; expose exported rules and configs.
New rules: import/export attributes
rules/sort-import-attributes.ts, rules/sort-import-attributes/types.ts, test/rules/sort-import-attributes.test.ts, docs/content/rules/sort-import-attributes.mdx
Add sort-import-attributes rule + types, schema, partition/newline/grouping logic, fixes, tests and docs.
New rules: export attributes
rules/sort-export-attributes.ts, rules/sort-export-attributes/types.ts, test/rules/sort-export-attributes.test.ts, docs/content/rules/sort-export-attributes.mdx
Add sort-export-attributes rule + types, schema, partition/newline/grouping logic, fixes, tests and docs.
Custom groups & partitioning (rules + docs)
rules/*, rules/*/types.ts, docs/content/rules/*.mdx
Migrate customGroups from object-map → array-based definitions; add partitionByComment, partitionByNewLine, newlinesBetween, per-group overrides (newlinesInside, fallbackSort, etc.); update schemas and defaults (customGroups: []) and docs with migration guidance.
Remove deprecated options
rules/* (many), rules/*/types.ts, docs/content/rules/*.mdx, tests
Remove groupKind, ignorePattern, tsconfigRootDir, destructureOnly, and DeprecatedCustomGroupsOption; update rules, schemas, tests, and docs to use groups/array customGroups; error payloads now include leftGroup/rightGroup where applicable.
Utils refactor & schema/types
utils/*.ts, utils/*-*.ts, utils/common-json-schemas.ts, types/common-options.ts
Remove deprecated custom-groups schema/type; add/rename helpers (e.g., filterOptionsByAllNamesMatch, filterOptionsByDeclarationCommentMatches), require array-based customGroups in helpers, simplify computeGroup signature (drop name).
Rules: defaultOptions typing & metadata
rules/*.ts (many)
Broaden option typing from Options[0]Options[number], add meta.defaultOptions: [defaultOptions] to many rules, and small internal cleanups (e.g., use toSorted).
Tests: adapt & extend
test/rules/*.test.ts, test/utils/*.test.ts
Add tests for new utilities and rules; remove tests for deprecated object-mapping and groupKind; update many tests to array customGroups, new group names, new error IDs, partition/newline scenarios, and options typing.
Docs: removal/fixes & new pages
docs/content/rules/*.mdx
Remove deprecated docs blocks (groupKind, ignorePattern, tsconfigRootDir), add rule pages for new rules, and update examples to array customGroups and new partition/newline options.
Other tooling & deps
eslint.config.ts, package.json (devDeps)
Dev-dependency upgrades (Astro, TypeScript, Shiki, Vite, ESLint-related packages) and ESLint config reference updates.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant ESLint as ESLint
  participant Rule as sort-import/export-attributes
  participant Groups as GroupsMatcher
  participant Partitioner as Partitioner
  participant Sorter as SortEngine
  participant Reporter as reportAllErrors

  ESLint->>Rule: Node (ImportDeclaration / ExportNamedDeclaration)
  Rule->>Groups: compute group for each attribute (predefined + array customGroups)
  Groups-->>Rule: groupName per attribute
  Rule->>Partitioner: partition attributes (partitionByNewLine / partitionByComment)
  Partitioner-->>Rule: partitions[]
  loop per partition
    Rule->>Sorter: apply per-group overrides (newlinesBetween/newlinesInside/fallbackSort)
    Sorter-->>Rule: sorted nodes + ordering metadata
    Rule->>Reporter: report spacing/group/order errors (includes leftGroup/rightGroup)
  end
Loading

Estimated code review effort

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

Possibly related PRs

Suggested reviewers

  • hugop95

Pre-merge checks

❌ Failed checks (3 warnings)
Check name Status Explanation Resolution
Linked Issues Check ⚠️ Warning The changes successfully remove deprecated APIs, convert the project to ESM, update package engines to drop Node.js v18 support, and implement the new sort-import-attributes rule, but they omit the requested createSortingRule helper, the sort-regexp rule, full migration to the Vitest rule tester, and dropping of ESLint v8 support. To comply with issue #566, add the createSortingRule abstraction, implement the sort-regexp rule, fully migrate tests to Vitest’s Rule Tester, and ensure support for ESLint v8 is removed or documented.
Out of Scope Changes Check ⚠️ Warning The PR introduces a new sort-export-attributes rule that was not specified in the linked issue objectives and includes broad devDependency upgrades unrelated to the release requirements, which appear outside the defined scope for this release. Consider removing or isolating the sort-export-attributes addition unless it is justified by updated objectives, and limit dependency updates to only those needed for the stated release goals.
Description Check ⚠️ Warning The pull request description only contains “Close #566,” and does not follow the required template sections such as a comprehensive Description, Additional context, purpose checklist, or adherence to the repository’s description format. Please expand the description to include the “Description” and “Additional context” sections per the repository template, summarizing what the PR solves, referencing relevant issues, and completing the purpose checklist.
✅ Passed checks (2 passed)
Check name Status Explanation
Title Check ✅ Passed The title “release v5.0.0” clearly reflects that the pull request’s primary purpose is to ship version 5.0.0 and concisely describes the main change as a release.
Docstring Coverage ✅ Passed No functions found in the changes. Docstring coverage check skipped.

📜 Recent 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 576712c and b0c8408.

⛔ 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 (4 hunks)

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

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 (b0c8408).

Additional details and impacted files
@@            Coverage Diff             @@
##              main      #569    +/-   ##
==========================================
  Coverage   100.00%   100.00%            
==========================================
  Files          101       108     +7     
  Lines         8565      8875   +310     
  Branches      1688      1693     +5     
==========================================
+ Hits          8565      8875   +310     

☔ 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 +255 to +263
<sub>type: `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.

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 newlinesBetween type and values.

The rule accepts 'always' | 'never' | number | 'ignore', but docs show only number | 'ignore'.

-<sub>type: `number | 'ignore'`</sub>
+<sub>type: `'always' | 'never' | number | '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.
📝 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
<sub>type: `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.
<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.
- `'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.
🤖 Prompt for AI Agents
In docs/content/rules/sort-decorators.mdx around lines 255 to 263, the
documented type and allowed values for the newlinesBetween option are wrong:
update the type annotation to include 'always' | 'never' | number | 'ignore'
(instead of only number | 'ignore'), adjust the default if needed, and expand
the bullet list to document the 'always' and 'never' cases (e.g., 'always' —
require a newline between groups; 'never' — forbid newlines between groups),
while keeping the existing descriptions for numeric values and 'ignore'.

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.

Comment on lines +368 to +378
interface CustomGroupAnyOfDefinition {
groupName: string
type?: 'alphabetical' | 'natural' | 'line-length' | '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 }[]
}>
}
```
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 CustomGroupAnyOfDefinition typings (fallbackSort, newlinesInside).

Same issue as above.

 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 }[]
   }>
 }
📝 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 CustomGroupAnyOfDefinition {
groupName: string
type?: 'alphabetical' | 'natural' | 'line-length' | '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 }[]
}>
}
```
interface CustomGroupAnyOfDefinition {
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
anyOf: Array<{
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 368 to 379, the
CustomGroupAnyOfDefinition typings for fallbackSort and newlinesInside are
incorrect; update fallbackSort to be optional and to mirror the main sort
options (i.e. fallbackSort?: { type?: 'alphabetical' | 'natural' | 'line-length'
| 'unsorted'; order?: 'asc' | 'desc' }) and update newlinesInside to accept
either a single number or a bounds object (e.g. newlinesInside?: number | {
min?: number; max?: number }) so it matches the other definitions in this file.

Comment on lines 19 to 21
customGroups:
| CustomGroupsOption<SingleCustomGroup>
| DeprecatedCustomGroupsOption
partitionByComment: PartitionByCommentOption
newlinesBetween: NewlinesBetweenOption
groups: GroupsOptions<Group>
Copy link

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

Remove DeprecatedCustomGroupsOption from public Options (docs/runtime mismatch).

Docs say the object-based customGroups API is removed in v5, but the type still allows DeprecatedCustomGroupsOption. This will compile while failing at runtime schema, confusing users.

Apply:

-    customGroups:
-      | CustomGroupsOption<SingleCustomGroup>
-      | DeprecatedCustomGroupsOption
+    customGroups: CustomGroupsOption<SingleCustomGroup>

To find any lingering legacy usages/tests:


🏁 Script executed:

#!/bin/bash
rg -nP "customGroups:\s*\{" -g "test/**.ts" -g "docs/**"
rg -n "DeprecatedCustomGroupsOption"

Length of output: 3493


Remove DeprecatedCustomGroupsOption across all APIs, utilities, and docs

  • DeprecatedCustomGroupsOption remains referenced in numerous rule‐type definitions (e.g. sort‐decorators, sort‐objects, sort‐imports, sort‐jsx‐props, sort‐heritage‐clauses, etc.), utility modules under utils/, and examples in docs/content/rules/*.
  • Removing it only in rules/sort-decorators/types.ts is incomplete—every occurrence must be expunged or replaced with CustomGroupsOption, and all documentation examples updated to match the v5 API.
  • Delete the type alias in types/common-options.ts and any related runtime validation logic that still expects the deprecated shape.
🤖 Prompt for AI Agents
In rules/sort-decorators/types.ts around lines 19 to 24, the type
DeprecatedCustomGroupsOption is still referenced; remove this deprecated type
and replace its usages with CustomGroupsOption across the codebase: update every
rule-type file (sort-decorators, sort-objects, sort-imports, sort-jsx-props,
sort-heritage-clauses, etc.), all utility modules under utils/, and
documentation examples in docs/content/rules/* to use CustomGroupsOption only;
delete the DeprecatedCustomGroupsOption alias from types/common-options.ts and
remove any runtime validation/guards that expect the deprecated shape, ensuring
validation, tests, and examples conform to the v5 API shape and build after
changes.

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.

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.

🛠️ Refactor suggestion

⚠️ Potential issue

Fix terminology and align RegExpPattern shape with types below.

  • “class decorators” is incorrect for this rule; use “heritage clauses”.
  • In RegExpPattern examples, flags should be optional to match the interfaces later (flags?: string).
 ### partitionByComment

 <sub>default: `false`</sub>

-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.
+- `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.
+- `{ block: boolean | RegExpPattern | RegExpPattern[]; line: boolean | RegExpPattern | RegExpPattern[] }` — Specify which block and line comments should act as delimiters.
📝 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
### 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.
### partitionByComment
<sub>default: `false`</sub>
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[]` — 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.
🤖 Prompt for AI Agents
In docs/content/rules/sort-heritage-clauses.mdx around lines 148 to 159, replace
the incorrect phrase “class decorators” with “heritage clauses” and update the
RegExpPattern shape descriptions to match the interfaces used later by making
flags optional (use flags?: string wording); ensure each listed RegExpPattern
example reflects the optional flags (both single and array variants) and keep
the same overall option descriptions and examples.

Comment on lines +94 to 96
/** Extended sorting node for named import specifiers. */
export type SortNamedImportsSortingNode = SortingNode<TSESTree.ImportClause>

Copy link

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

Bug: wrong AST node type for SortNamedImportsSortingNode

Sorting nodes in the rule hold ImportSpecifier, not ImportClause. This causes an incorrect public type and potential type errors.

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>

Run to confirm no remaining references to ImportClause in this context and that the type matches usage:


🏁 Script executed:

#!/bin/bash
rg -nP --type=ts -C2 '\bSortNamedImportsSortingNode\b'
rg -nP --type=ts -C2 'node:\s*specifier' rules/sort-named-imports.ts
rg -nP --type=ts -C2 'ImportClause' rules/sort-named-imports

Length of output: 2013


Fix SortNamedImportsSortingNode: use TSESTree.ImportSpecifier

Sorting nodes are built from ImportSpecifier (the code passes specifier as node), so the exported type must be SortingNode<TSESTree.ImportSpecifier>.

-/** 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>

Location: rules/sort-named-imports/types.ts:95

📝 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
/** 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>
🤖 Prompt for AI Agents
In rules/sort-named-imports/types.ts around lines 94 to 96, the exported type
SortNamedImportsSortingNode is incorrectly using TSESTree.ImportClause but the
sorting nodes are constructed from ImportSpecifier; update the type to
SortingNode<TSESTree.ImportSpecifier> so the exported type matches the actual
node kind passed in the code and any downstream usage.

Comment on lines +349 to +337
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

Pass newlinesBetweenValueGetter to enable spacing diagnostics.

Without newlinesBetweenValueGetter, reportAllErrors can't 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'
🤖 Prompt for AI Agents
In rules/sort-object-types.ts around lines 349 to 357, reportAllErrors is called
without the newlinesBetweenValueGetter so it cannot compute missed/extra
blank-line errors; add the missing import "import { getLinesBetween } from
'../utils/get-lines-between'" at the top of the file and pass
newlinesBetweenValueGetter: getLinesBetween (or equivalent getter) into the
reportAllErrors call alongside the existing arguments so the function can detect
spacing diagnostics when options.newlinesBetween is set.

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 (9)
docs/content/rules/sort-sets.mdx (1)

450-452: Broken link to tests

Tests live under test/rules/sort-sets.test.ts now.

Update:

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

67-83: Default still uses deprecated customGroups shape. Switch to array.

For v5, defaultOptions.customGroups should be [] (array), not {} (object).

Apply:

-  customGroups: {},
+  customGroups: [],

16-16: Schema still allows deprecated customGroups object. Remove it for v5.

Drop deprecatedCustomGroupsJsonSchema from oneOf to enforce the new API.

Apply:

-import {
-  buildUseConfigurationIfJsonSchema,
-  buildCustomGroupsArrayJsonSchema,
-  deprecatedCustomGroupsJsonSchema,
+import {
+  buildUseConfigurationIfJsonSchema,
+  buildCustomGroupsArrayJsonSchema,
   partitionByCommentJsonSchema,
   partitionByNewLineJsonSchema,
   newlinesBetweenJsonSchema,
   buildCommonJsonSchemas,
   groupsJsonSchema,
   regexJsonSchema,
 } from '../utils/common-json-schemas'
-      customGroups: {
-        oneOf: [
-          deprecatedCustomGroupsJsonSchema,
-          buildCustomGroupsArrayJsonSchema({
-            additionalFallbackSortProperties: { sortBy: sortByJsonSchema },
-            singleCustomGroupJsonSchema,
-          }),
-        ],
-      },
+      customGroups: buildCustomGroupsArrayJsonSchema({
+        additionalFallbackSortProperties: { sortBy: sortByJsonSchema },
+        singleCustomGroupJsonSchema,
+      }),

Also applies to: 93-101


85-119: Repo-wide cleanup required: deprecated customGroups types/schemas still referenced

Multiple files still reference DeprecatedCustomGroupsOption and deprecatedCustomGroupsJsonSchema — replace usages with CustomGroupsOption and the updated JSON schema, and update tests/docs.

  • Definitions to update: types/common-options.ts (DeprecatedCustomGroupsOption ~line 461), utils/common-json-schemas.ts (deprecatedCustomGroupsJsonSchema ~line 192).
  • Key consumers (non‑exhaustive): utils/* (validate-generated-groups-configuration.ts, make-newlines-between-fixes.ts, make-comment-above-fixes.ts, make-fixes.ts, get-newlines-between-option.ts, get-newlines-between-errors.ts, get-custom-groups-compare-options.ts, get-comment-above-that-should-exist.ts, compute-group.ts).
  • Rule files to sweep: rules/sort-object-types.ts, rules/sort-objects.ts, rules/sort-imports.ts, rules/sort-jsx-props.ts, rules/sort-decorators.ts, rules/sort-heritage-clauses.ts, rules/sort-enums.ts, rules/sort-interfaces.ts.
  • Tests/docs: many test files under test/ and docs/content/ reference customGroups — update examples and assertions.

Action: perform a repo-wide replace of the deprecated type/schema, update calling sites, and adjust tests/docs; run the test suite to verify no regressions.

package.json (1)

125-127: Align peer range with stated drop of ESLint v8

PR objective says “Drop legacy ESLint v8 support,” but peerDependencies still allow v8. Bump to v9+.

-  "peerDependencies": {
-    "eslint": ">=8.45.0"
-  },
+  "peerDependencies": {
+    "eslint": ">=9.0.0"
+  },
docs/content/rules/sort-heritage-clauses.mdx (2)

185-189: Update groups type to reflect inline newlinesBetween objects

Docs currently state Array<string | string[]> but you also support spacing objects between groups.

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

321-333: Migrate the example to the new array-based customGroups

This section still shows the removed object API.

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

272-275: Correct groups option type to include separator/metadata objects.

Schema allows objects with newlinesBetween/commentAbove; docs currently don’t.

 <sub>
-  type: `Array<string | string[]>`
+  type: `Array<string | string[] | { newlinesBetween?: 'always' | 'never' | number; commentAbove?: string | { pattern: string; flags?: string } | Array<string | { pattern: string; flags?: string }>} >`
 </sub>
rules/sort-decorators.ts (1)

259-288: Honor partition boundaries when reporting; avoid cross-partition false positives.

Currently, nodes are flattened and reported once, so edges across partitions may incorrectly trigger order/spacing errors. Mirror the per-partition flow used in sort-heritage-clauses.

-  function sortNodesExcludingEslintDisabled(
-    ignoreEslintDisabledNodes: boolean,
-  ): SortDecoratorsSortingNode[] {
-    return formattedMembers.flatMap(nodes =>
-      sortNodesByGroups({
-        getOptionsByGroupIndex:
-          buildGetCustomGroupOverriddenOptionsFunction(options),
-        ignoreEslintDisabledNodes,
-        groups: options.groups,
-        nodes,
-      }),
-    )
-  }
-  let nodes = formattedMembers.flat()
-
-  reportAllErrors<MessageId>({
-    availableMessageIds: {
-      missedSpacingBetweenMembers: 'missedSpacingBetweenDecorators',
-      extraSpacingBetweenMembers: 'extraSpacingBetweenDecorators',
-      unexpectedGroupOrder: 'unexpectedDecoratorsGroupOrder',
-      unexpectedOrder: 'unexpectedDecoratorsOrder',
-    },
-    ignoreFirstNodeHighestBlockComment: true,
-    sortNodesExcludingEslintDisabled,
-    sourceCode,
-    options,
-    context,
-    nodes,
-  })
+  for (let nodes of formattedMembers) {
+    function createSortNodesExcludingEslintDisabled(
+      sortingNodes: SortDecoratorsSortingNode[],
+    ) {
+      return function (ignoreEslintDisabledNodes: boolean) {
+        return sortNodesByGroups({
+          getOptionsByGroupIndex:
+            buildGetCustomGroupOverriddenOptionsFunction(options),
+          ignoreEslintDisabledNodes,
+          groups: options.groups,
+          nodes: sortingNodes,
+        })
+      }
+    }
+
+    reportAllErrors<MessageId>({
+      availableMessageIds: {
+        missedSpacingBetweenMembers: 'missedSpacingBetweenDecorators',
+        extraSpacingBetweenMembers: 'extraSpacingBetweenDecorators',
+        unexpectedGroupOrder: 'unexpectedDecoratorsGroupOrder',
+        unexpectedOrder: 'unexpectedDecoratorsOrder',
+      },
+      ignoreFirstNodeHighestBlockComment: true,
+      sortNodesExcludingEslintDisabled:
+        createSortNodesExcludingEslintDisabled(nodes),
+      sourceCode,
+      options,
+      context,
+      nodes,
+    })
+  }
♻️ Duplicate comments (5)
vite.config.ts (1)

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

Node 20 doesn’t support import.meta.dirname. Replace with an ESM-safe __dirname shim.

Apply:

 import dts from 'vite-plugin-dts'
 import path from 'node:path'
+import { fileURLToPath } from 'node:url'
+
+// ESM-safe __dirname for Node 20+
+const __dirname = path.dirname(fileURLToPath(import.meta.url))

       entry: [
-        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'),
+        path.join(__dirname, 'index.ts'),
+        path.join(__dirname, 'types'),
+        path.join(__dirname, 'rules'),
+        path.join(__dirname, 'utils'),
       ],

Also applies to: 29-33

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

19-24: Remove DeprecatedCustomGroupsOption from public Options (v5).

Keep only CustomGroupsOption to match docs/runtime.

Apply:

-    customGroups:
-      | CustomGroupsOption<SingleCustomGroup>
-      | DeprecatedCustomGroupsOption
+    customGroups: CustomGroupsOption<SingleCustomGroup>
docs/content/rules/sort-decorators.mdx (3)

255-263: Fix newlinesBetween type and values to match schema.

Docs omit 'always' and 'never'. Update type and bullets.

-<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.
+- `'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.

352-359: Align CustomGroupDefinition typings (fallbackSort, newlinesInside).

Match runtime/types: broaden fallbackSort; allow 'always' | 'never' | number for newlinesInside.

 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 }[]
 }

367-378: Align CustomGroupAnyOfDefinition typings (fallbackSort, newlinesInside).

Same corrections as above.

 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 }[]
   }>
 }
🧹 Nitpick comments (11)
docs/content/rules/sort-sets.mdx (1)

290-292: Terminology: say “Set elements”, not “Array elements”

This rule documents Sets; calling them “Array elements” here is confusing.

Apply:

- - `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.
test/rules/sort-sets.test.ts (1)

965-993: anyOf test isn’t exercising a SpreadElement

Code uses the string '...foo' instead of a spread (...foo), so the spread selector path isn’t covered.

Consider:

  • In code/output blocks, replace '...foo' with ...foo (no quotes) to cover both literal and spread cases.
test/rules/sort-array-includes.test.ts (1)

1148-1169: anyOf test doesn’t cover a real spread

'...foo' is a string literal; the spread branch isn’t validated.

Change '...foo' → ...foo (no quotes) in code/output to exercise the spread selector path too.

vite.config.ts (1)

19-21: Remove exports: 'auto' for ES-only build

Rollup’s output.exports is for CJS; with formats: ['es'] it’s redundant.

       output: {
         preserveModules: true,
-        exports: 'auto',
       },
package.json (2)

15-25: Add explicit "import" condition to exports

ESM-only packages typically expose "import". Keeping "default" as a fallback is fine.

   "exports": {
     ".": {
       "types": "./dist/index.d.ts",
-      "default": "./dist/index.js"
+      "import": "./dist/index.js",
+      "default": "./dist/index.js"
     },
     "./alphabet": {
       "types": "./dist/alphabet.d.ts",
-      "default": "./dist/utils/alphabet.js"
+      "import": "./dist/utils/alphabet.js",
+      "default": "./dist/utils/alphabet.js"
     },
     "./package.json": "./package.json"
   },

13-15: Consider declaring sideEffects: false

If the plugin has no top-level side effects (typical for ESLint plugins), mark it for better tree-shaking.

   "license": "MIT",
   "author": "Azat S. <[email protected]>",
+  "sideEffects": false,
   "type": "module",
rules/sort-heritage-clauses/types.ts (1)

31-35: Nit: avoid reserved-word confusion with 'unknown'

Using 'unknown' as a string literal is fine, but consider a more explicit literal like 'unknown-group' to avoid confusion with TS's unknown type in tooling.

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

413-415: Fix test link path

Tests live under test/rules now.

-- [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)

38-46: Consider correcting the line-length “Try it out” example

Docs say shorter lines first, but the example shows longer-first ordering. Either set order: 'desc' in the snippet or flip the items.

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

251-252: Clarify partitionByNewLine behavior.

Make it explicit that sorting still occurs within partitions.

-When `true`, the rule will not sort the decorators if there is an empty line between them.
+When `true`, any blank line acts as a partition boundary; sorting is applied within each partition only (not across partitions).

264-266: Grammar: “option” (singular).

-You can also enforce the newline behavior between two specific groups through the `groups` options.
+You can also enforce the newline behavior between two specific groups through the `groups` option.
📜 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-named-imports.mdx
  • docs/content/rules/sort-exports.mdx
  • docs/content/rules/sort-named-exports.mdx
  • test/rules/sort-object-types.test.ts
  • rules/sort-object-types/types.ts
  • rules/sort-interfaces.ts
  • rules/sort-array-includes/types.ts
  • test/rules/sort-exports.test.ts
  • docs/content/rules/sort-interfaces.mdx
  • rules/sort-exports/types.ts
  • docs/content/rules/sort-object-types.mdx
  • test/rules/sort-interfaces.test.ts
✅ Files skipped from review due to trivial changes (1)
  • docs/content/rules/sort-intersection-types.mdx
🚧 Files skipped from review as they are similar to previous changes (6)
  • docs/content/rules/sort-array-includes.mdx
  • rules/sort-named-imports.ts
  • test/rules/sort-named-imports.test.ts
  • rules/sort-named-exports/types.ts
  • rules/sort-named-imports/types.ts
  • rules/sort-named-exports.ts
🧰 Additional context used
🧬 Code graph analysis (7)
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-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-object-types.ts (13)
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/get-custom-groups-compare-options.ts (1)
  • getCustomGroupsCompareOptions (93-124)
utils/report-all-errors.ts (1)
  • reportAllErrors (203-326)
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/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-decorators.ts (7)
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-generated-groups-configuration.ts (1)
  • validateGeneratedGroupsConfiguration (73-96)
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)
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-heritage-clauses.ts (10)
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)
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)
🪛 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 (35)
docs/content/rules/sort-sets.mdx (2)

274-274: Default groups doc looks correct

Defaulting to groups: ['literal'] matches the new API.


398-401: Examples updated to groups API — LGTM

Both Flat and Legacy config snippets correctly use groups: ['literal'].

Also applies to: 428-431

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

235-241: Explicit groups in partitioned scenarios — good

Using groups: ['spread'] with partitionByNewLine is consistent with the new API.

Also applies to: 1757-1763, 3279-3285


243-253: Switched to group-order message IDs — good

unexpectedSetsGroupOrder with leftGroup/rightGroup fits the groups model.

Also applies to: 255-262, 1767-1775, 1777-1784, 3289-3297, 3299-3306

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

263-268: Adoption of groups in partitioned tests — LGTM

groups: ['spread'] usage is correct across partitions.

Also applies to: 313-320, 2060-2065, 2111-2116, 3836-3841, 3888-3893


271-281: Message IDs now reflect group ordering — LGTM

unexpectedArrayIncludesGroupOrder + leftGroup/rightGroup aligns with API changes.

Also applies to: 282-291, 476-486, 487-495, 4048-4059, 4060-4068


867-873: Custom group ordering examples — LGTM

groups: ['spread', 'literal'] with group-order errors is correct.

Also applies to: 2637-2669, 4414-4446

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

116-122: Good migration to groups-based API (type exports).

Using groups: ['type-export'] with the new unexpectedNamedExportsGroupOrder message is correct and keeps intent explicit.

Also applies to: 167-167


1486-1492: Consistent group-order assertions for natural sort.

The rightGroup/leftGroup data and groups option mirror the alphabetical suite—nice consistency.

Also applies to: 1537-1537


2856-2862: Line-length suite aligns with groups model.

The partition-by-comment + groups: ['type-export'] path looks sound.

Also applies to: 2907-2907

rules/sort-exports.ts (2)

50-52: Type alias simplification is correct.

Dropping groupKind from the node shape and aliasing to SortingNode<...> matches the new common model.


151-163: Flattened partitions + centralized reporting look correct.

  • Sorting per partition via sortNodesByGroups and then reportAllErrors is consistent with other rules.
  • buildGetCustomGroupOverriddenOptionsFunction returning only options is fine (nodeValue getters default).

Also applies to: 165-179

rules/sort-array-includes.ts (4)

56-58: Type alias matches shared SortingNode contract.

No groupKind leakage—good.


68-69: Sensible default: groups ['literal'].

Preserves “literals before spreads” behavior without legacy groupKind.


196-198: Selector derivation is correct.

Mapping SpreadElement → 'spread', others → 'literal' cleanly feeds predefined groups.


245-257: Sorting pipeline mirrors shared utils correctly.

Partitioning → grouped sort → reportAllErrors is aligned with v5 architecture.

Also applies to: 259-267

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

216-223: Skipping call/construct signatures is correct.

They are not sortable “members” here, so continuing early avoids noise.


228-259: Selector/modifier derivation looks solid.

  • Adds index-signature/method/member/property in priority order.
  • Tracks optional/required and multiline.

260-268: Value extraction for sort-by-value is correct.

Capturing TSPropertySignature annotation text enables 'value' sorting.


269-287: Group computation aligns with new predefined/custom groups flow.

Precompute + computeGroup usage is consistent with utilities.


288-313: Partitioning logic is correct.

shouldPartition + partitionId assignment mirrors other rules.


316-347: Per-group overrides are correctly applied.

getCustomGroupsCompareOptions supplies sortBy/fallback getters; group-level ignore on missing value is correct.


349-357: Centralized error reporting wiring is correct.

Pipeline matches shared reportAllErrors contract.


85-119: Confirm whether ignorePattern is intended to remain in v5.

PR objectives mention removing legacy options (incl. ignorePattern). If it’s to be removed, excise it here as well (schema, defaults, logic). If it stays, ensure docs reflect it.

Would you like a follow-up patch to remove ignorePattern, or should we keep it and update docs?

package.json (1)

41-43: No action required — require('./package.json') works as used by the release scripts.
Ran: node -p "require('./package.json').version" → 4.15.0
Location: package.json (lines 41–43)

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

15-25: LGTM: Options shape matches new API (groups/newlines/partitions)

Types line up with GroupsOptions, PartitionByCommentOption, and NewlinesBetweenOption.

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

364-407: LGTM: elementNamePattern variants thoroughly covered

Covers string, array, regex, and mixed-array cases for grouping. Good breadth.


409-457: LGTM: per-group sort overrides validated

Validates type/order override on a custom group vs global defaults.


562-626: LGTM: spacing removal with newlinesBetween ('never'/0) checks

Good to see both error kinds and output normalization asserted.


1052-1096: LGTM: newlinesInside behavior covered

Covers 'always'/1 and 'never'/0 within groups.

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

665-753: LGTM: decorator grouping by elementNamePattern variants

Mirrors heritage-clauses coverage; consistent and comprehensive.


808-883: LGTM: per-group sort override + fallbackSort tests

Ensures tie-break via fallback and group-local type/order precedence.


1110-1177: LGTM: newline insertion with newlinesBetween ('always'/1)

Covers error messaging and output formatting well.

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

518-519: Verify “Test source” link path.

Tests appear to live under test/rules/sort-decorators.test.ts now; update if so.

-- [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-heritage-clauses.ts (1)

182-211: Good: partition-aware reporting avoids cross-partition errors.

Per-partition sort+report mirrors shouldPartition semantics and prevents false positives.

Comment on lines +265 to +273
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

Expand CustomGroupDefinition types (add 'custom'; correct newlinesInside union)

Matches the code and tests where 'custom' and 'always'/'never' are valid.

 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 }[]
 }
📝 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
elementNamePattern?: string | string[] | { pattern: string; flags?: string } | { pattern: string; flags?: string }[]
}
interface CustomGroupDefinition {
groupName: string
type?: 'alphabetical' | 'natural' | 'line-length' | 'custom' | 'unsorted'
order?: 'asc' | 'desc'
fallbackSort?: { type: string; order?: 'asc' | 'desc' }
newlinesInside?: 'always' | 'never' | number
elementNamePattern?: string | string[] | { pattern: string; flags?: string } | { pattern: string; flags?: string }[]
}
🤖 Prompt for AI Agents
In docs/content/rules/sort-heritage-clauses.mdx around lines 265-273, the
CustomGroupDefinition TypeScript declaration is missing the 'custom' option in
the type union and newlinesInside only allows number; update the type field to
include 'custom' (i.e. 'alphabetical' | 'natural' | 'line-length' | 'unsorted' |
'custom') and change newlinesInside to accept number | 'always' | 'never' to
match tests and implementation, then save and run the test suite to verify.

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

Caution

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

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

4903-4921: Duplicate enum member key ('m') in fixture

In “detects numeric enums correctly”, 'm' appears twice, which is invalid for enums and may confuse the test intent. Use unique keys.

           enum Enum {
             'i' = ~2, // -3
             'k' = -1,
             'j' = - 0.1,
             'e' = - (((1 + 1) * 2) ** 2) / 4 % 2, // 0
             'f' = 0,
             'h' = +1,
             'g' = 3 - 1, // 2
             'b' = 5^6, // 3
             'l' = 1 + 3, // 4
             'm' = 2.1 ** 2, // 4.41
             'a' = 20 >> 2, // 5
-            'm' = 7 & 6, // 6
+            'n' = 7 & 6, // 6
             'c' = 5 | 6, // 7
             'd' = 2 << 2, // 8
           }
package.json (1)

125-127: Peer range contradicts “drop ESLint v8” objective.

If v8 support is dropped, widen the peer to ESLint 9+ to prevent accidental installs on v8.

   "peerDependencies": {
-    "eslint": ">=8.45.0"
+    "eslint": ">=9.0.0"
   },
♻️ Duplicate comments (1)
package.json (1)

60-61: Deduplicate @typescript-eslint/types and align versions.

The package appears in both dependencies (^8.43.0) and devDependencies (^6.13.0). Keep a single entry (devDependencies is typical) and align to ^8.43.0 to avoid duplicate installs and type skew.

   "dependencies": {
-    "@typescript-eslint/types": "^8.43.0",
     "@typescript-eslint/utils": "^8.43.0",
     "natural-orderby": "^5.0.0"
   },
@@
   "devDependencies": {
@@
-    "@typescript-eslint/types": "^6.13.0",
+    "@typescript-eslint/types": "^8.43.0",

Also applies to: 84-84

🧹 Nitpick comments (3)
rules/sort-enums.ts (1)

145-149: Keep enum member name strictly typed as string

Using member.id.value directly risks a string | number drift if a numeric literal sneaks in; downstream code (e.g., doesCustomGroupMatch, dependencyNames: string[], and SortingNodeWithDependencies.name) is string-oriented. Coerce to string at the source to make the contract explicit.

-          let name =
-            member.id.type === 'Literal'
-              ? member.id.value
-              : sourceCode.getText(member.id)
+          let name: string =
+            member.id.type === 'Literal'
+              ? String(member.id.value)
+              : sourceCode.getText(member.id)
package.json (2)

28-30: Minor: simplify files path.

"files" entries don’t need the "./" prefix.

   "files": [
-    "./dist"
+    "dist"
   ],

41-43: Nit: use ESM-friendly version extraction in release scripts.

These commands rely on require in a Node REPL context; it works today but can be future-proofed by reading JSON via fs.

Alternative snippet:

  • node -p "JSON.parse(require('fs').readFileSync('./package.json','utf8')).version"
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

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

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (3)
  • package.json (4 hunks)
  • rules/sort-enums.ts (1 hunks)
  • test/rules/sort-enums.test.ts (6 hunks)
🧰 Additional context used
🪛 ESLint
test/rules/sort-enums.test.ts

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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)

🔇 Additional comments (3)
test/rules/sort-enums.test.ts (1)

66-74: LGTM: numeric-like enum keys migrated to string-literals

The updates to quote number-like enum member names align tests with TS grammar and the rule’s name handling. Looks good.

Also applies to: 90-103, 1626-1662, 1649-1662, 3188-3192, 3209-3213

package.json (2)

3-3: Version still 4.15.0 while releasing v5.0.0.

Confirm whether version bump is handled by the release script or should be committed in this PR. If manual, bump here.

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

20-23: Align "./alphabet" subpath export in package.json

exports['./alphabet'] currently maps "types" -> "./dist/alphabet.d.ts" and "default" -> "./dist/utils/alphabet.js"; dist/ is not present in the repo, so verify the intended build output and make the paths consistent.

If JS is at dist/alphabet.js:

 "./alphabet": {
-  "types": "./dist/alphabet.d.ts",
-  "default": "./dist/utils/alphabet.js"
+  "types": "./dist/alphabet.d.ts",
+  "default": "./dist/alphabet.js"
 },

If JS truly lives under dist/utils/, move the d.ts accordingly:

 "./alphabet": {
-  "types": "./dist/alphabet.d.ts",
-  "default": "./dist/utils/alphabet.js"
+  "types": "./dist/utils/alphabet.d.ts",
+  "default": "./dist/utils/alphabet.js"
 },

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

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-imports.mdx (2)

459-463: Fix grammar: “between above your groups”

Tighten the sentence.

-You may place `commentAbove` objects between above your groups to enforce the presence of a comment containing the
-content of `commentAbove`.
+You may place `commentAbove` objects above your groups to require a comment containing the value of `commentAbove`.

709-711: Mark "Legacy Config" as deprecated (planned removal in v5.0.0)

Multiple types/docs are annotated "Will be removed in v5.0.0" and the package still exposes legacy configs for ESLint v8; update all "Legacy Config" tabs (e.g., docs/content/rules/sort-imports.mdx:709–711) to indicate deprecation or remove them.

-      name: 'Legacy Config',
+      name: 'Legacy Config (ESLint v8 — deprecated)',
rules/sort-imports.ts (2)

566-581: Possible runtime NPE: doesCustomGroupMatch receives undefined selectors/modifiers for deprecated paths

computeGroupExceptUnknown is invoked before selectors/modifiers are populated (e.g., Lines 175–181), yet the matcher is called with non-null assertions. If doesCustomGroupMatch assumes arrays, this can throw.

   let computedCustomGroup = computeGroup({
     customGroupMatcher: customGroup =>
       doesCustomGroupMatch({
-        modifiers: modifiers!,
-        selectors: selectors!,
+        // Handle deprecated paths where these are intentionally unset
+        modifiers: modifiers ?? [],
+        selectors: selectors ?? [],
         elementName: name,
         customGroup,
       }),

126-135: Guard access to context.physicalFilename — fallback to context.filename

Some ESLint runtimes may not expose context.physicalFilename; use a safe fallback so tsconfig discovery can't break.

-          filePath: context.physicalFilename,
+          filePath:
+            // ESLint v9 exposes `physicalFilename`; fall back to `filename` if absent.
+            (context as any).physicalFilename ?? context.filename,

Location: rules/sort-imports.ts:129-133 (single occurrence found).

🧹 Nitpick comments (9)
docs/content/rules/sort-imports.mdx (5)

326-326: Clarify requirement wording for tsconfig-path selector

Recommend making it explicit that tsconfig.rootDir must be set in this rule’s tsconfig option.

-- 'tsconfig-path' — `tsconfig` [paths](https://www.typescriptlang.org/tsconfig/#paths) alias imports. Requires [`tsconfig.rootDir`](#tsconfig) to be set.
+- 'tsconfig-path' — `tsconfig` [paths](https://www.typescriptlang.org/tsconfig/#paths) alias imports. Requires setting [`tsconfig.rootDir`](#tsconfig) in this rule’s `tsconfig` option.

197-203: Typo case: “Refer To” → “Refer to”

-Specifies the sorting locales. Refer To [String.prototype.localeCompare() - locales](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/localeCompare#locales).
+Specifies the sorting locales. Refer to [String.prototype.localeCompare() - locales](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/localeCompare#locales).

229-232: Make flags optional (align with other regex-typed options) or confirm intended difference

Elsewhere (elementNamePattern) uses flags?: string, but here RegExpPattern shows flags: string. Align or document why it differs.

-- `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.

604-612: Match lodash subpaths in example

Use a regex that also matches lodash/… subpaths.

     {
       groupName: 'lodash',
-      elementNamePattern: 'lodash',
+      elementNamePattern: '^lodash($|/)',
     }

38-46: Minor wording: “Supporting for new import types”

Use concise phrasing.

-1. Supporting for new import types:
+1. Support for additional import types:
test/rules/sort-imports.test.ts (3)

6374-6410: Same here: nested tsconfig LGTM; add after reset for stability.

The tsconfig: { rootDir: '.' } update aligns with the new options. Mirror an after reset next to the existing before hook.

         before: () => {
           mockReadClosestTsConfigByPathWith({
             paths: {
               $path: ['./path'],
             },
           })
         },
+        after: () => {
+          vi.resetAllMocks()
+        },

10136-10173: Consistent tsconfig usage; add after reset to prevent cross-test bleed.

Matches the new API. Add after: vi.resetAllMocks() adjacent to before.

         before: () => {
           mockReadClosestTsConfigByPathWith({
             paths: {
               $path: ['./path'],
             },
           })
         },
+        after: () => {
+          vi.resetAllMocks()
+        },

2554-2599: Add after hook to reset mocks; migrate/verify leftover tsconfigRootDir usages.

Add an after hook to avoid spy leakage from mockReadClosestTsConfigByPathWith.

         before: () => {
           mockReadClosestTsConfigByPathWith({
             paths: {
               $path: ['./path'],
             },
           })
         },
+        after: () => {
+          vi.resetAllMocks()
+        },

rg shows tsconfigRootDir still in rules/sort-imports.ts, read-closest-ts-config-by-path.ts and several tests — update those callers/tests to the nested tsconfig option or keep the compatibility mapping in place.

rules/sort-imports.ts (1)

72-98: Drop of standalone tsconfigRootDir: typing LGTM; prefer const + satisfies for defaultOptions

Good switch to using only tsconfig.rootDir. Minor type/style tweak to prevent widening and accidental mutation:

-let defaultOptions: Required<Omit<Options[0], 'maxLineLength' | 'tsconfig'>> &
-  Pick<Options[0], 'maxLineLength' | 'tsconfig'> = {
+const defaultOptions = {
   groups: [
     'type-import',
     ['value-builtin', 'value-external'],
     'type-internal',
     'value-internal',
     ['type-parent', 'type-sibling', 'type-index'],
     ['value-parent', 'value-sibling', 'value-index'],
     'ts-equals-import',
     'unknown',
   ],
   internalPattern: ['^~/.+', '^@/.+'],
   fallbackSort: { type: 'unsorted' },
   partitionByComment: false,
   partitionByNewLine: false,
   specialCharacters: 'keep',
   sortSideEffects: false,
   type: 'alphabetical',
   environment: 'node',
   newlinesBetween: 1,
   customGroups: [],
   ignoreCase: true,
   locales: 'en-US',
   alphabet: '',
   order: 'asc',
-}
+} satisfies Required<Omit<Options[0], 'maxLineLength' | 'tsconfig'>> &
+  Pick<Options[0], 'maxLineLength' | 'tsconfig'>
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between fcc1813 and 31585bd.

📒 Files selected for processing (4)
  • docs/content/rules/sort-imports.mdx (1 hunks)
  • rules/sort-imports.ts (3 hunks)
  • rules/sort-imports/types.ts (0 hunks)
  • test/rules/sort-imports.test.ts (7 hunks)
💤 Files with no reviewable changes (1)
  • rules/sort-imports/types.ts
🧰 Additional context used
🧬 Code graph analysis (1)
rules/sort-imports.ts (1)
rules/sort-imports/types.ts (1)
  • Options (30-151)
🔇 Additional comments (5)
docs/content/rules/sort-imports.mdx (1)

724-726: Links verified — no update required

Both files exist at rules/sort-imports.ts and test/rules/sort-imports.test.ts, so the documented "Rule source" and "Test source" links are correct.

test/rules/sort-imports.test.ts (4)

12029-12033: LGTM: migrated to tsconfig.rootDir in misc/internal classification test.


12053-12057: LGTM: external classification uses tsconfig.rootDir correctly.


12077-12083: LGTM: unresolved imports default to external with tsconfig.rootDir.


12105-12113: LGTM: fallback path (TS unavailable) with tsconfig.rootDir is correct.

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-object-types.ts (1)

67-83: Remove deprecated ignorePattern for v5.0.0.

Release goals state deprecated options (including ignorePattern) must be removed. It’s still present in defaultOptions, jsonSchema, and used at runtime. Replace with useConfigurationIf.declarationMatchesPattern (or instruct users to set type: 'unsorted' under a matching condition).

Apply:

@@
 let defaultOptions: Required<Options[0]> = {
   fallbackSort: { type: 'unsorted', sortBy: 'name' },
   partitionByComment: false,
   partitionByNewLine: false,
   newlinesBetween: 'ignore',
   specialCharacters: 'keep',
   useConfigurationIf: {},
   type: 'alphabetical',
-  ignorePattern: [],
   ignoreCase: true,
   customGroups: {},
   locales: 'en-US',
   sortBy: 'name',
   alphabet: '',
   order: 'asc',
   groups: [],
 }
@@
       newlinesBetween: newlinesBetweenJsonSchema,
-      ignorePattern: regexJsonSchema,
       sortBy: sortByJsonSchema,
       groups: groupsJsonSchema,
@@
-  if (parentNodeName && matches(parentNodeName, options.ignorePattern)) {
-    return
-  }
+  // No ignorePattern in v5; use `useConfigurationIf` to scope behavior instead.

Also applies to: 110-113, 207-209

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

164-179: Remove vestigial 'multiline' selector mapping.

AllowedModifiersPerSelector includes a 'multiline' key, but 'multiline' is no longer a Selector. Keeping it is inconsistent and confusing.

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 cannot have modifiers. */
   'index-signature': never
 }

222-230: Tighten IndexSignatureGroup to exclude modifiers.

Docs say index signatures can’t have modifiers, but the type currently composes modifier permutations. Make it a plain 'index-signature'.

Apply:

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

99-109: Remove deprecated ignorePattern from Options for v5.0.0.

The type still exposes ignorePattern with a deprecation note “Will be removed in v5.0.0.” Since this is v5, drop it from Options.

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

8193-8207: Update ignore test to v5 API (replace ignorePattern).

ignorePattern is removed in v5. Rewrite the test to scope an unsorted configuration via useConfigurationIf.declarationMatchesPattern.

Apply:

-      await valid({
-        code: dedent`
-          type IgnoreType = {
-            b: 'b'
-            a: 'a'
-          }
-        `,
-        options: [
-          {
-            ignorePattern: ['Ignore'],
-          },
-        ],
-      })
+      await valid({
+        code: dedent`
+          type IgnoreType = {
+            b: 'b'
+            a: 'a'
+          }
+        `,
+        options: [
+          {
+            useConfigurationIf: { declarationMatchesPattern: 'Ignore' },
+            type: 'unsorted',
+          },
+        ],
+      })
♻️ Duplicate comments (1)
rules/sort-object-types.ts (1)

348-356: Pass newlinesBetweenValueGetter to enable spacing diagnostics.

Without it, reportAllErrors can’t compute missed/extra blank lines reliably when newlinesBetween is configured. This was raised before.

Apply:

@@
-import { reportAllErrors } from '../utils/report-all-errors'
+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,
   })
🧹 Nitpick comments (10)
test/rules/sort-interfaces.test.ts (1)

4-4: Address ESLint no-unsafe-call on tagged template (dedent).

If CI flags @typescript-eslint/no-unsafe-call for dedent\...`, add @types/dedentor switch to a typed helper (e.g.,common-tagsstripIndent`) for tests.

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

155-155: Use const for immutable list

allSelectors is not reassigned. Prefer const.

-export let allSelectors: Selector[] = ['prop']
+export const allSelectors: Selector[] = ['prop']
test/rules/sort-jsx-props.test.ts (2)

4383-4387: Schema validation test is a good safeguard; add a negative case

Consider asserting that invalid configs like customGroups: [{ selector: 'shorthand' }] are rejected to lock the contract after narrowing Selector.

Example to add near this test:

await expect(
  validateRuleJsonSchema([
    // emulate a rule schema that would allow invalid selector; should fail against current schema
    { properties: { customGroups: { properties: { selector: { enum: ['shorthand'] } } } } } as any,
  ]),
).rejects.toThrow()

4356-4368: Nice coverage for mixing predefined and custom groups

This ensures 'multiline-prop'/'shorthand-prop' coexist with custom names. Consider adding one case for 'shorthand-multiline-prop' if supported by JoinWithDash to fully exercise combinations.

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

151-158: Selector union cleanup looks good; trim dead keys in AllowedModifiersPerSelector

With 'multiline' no longer a Selector, keys 'multiline' and 'index-signature' in AllowedModifiersPerSelector are unused noise. Remove for clarity.

 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
 }

293-293: Use const for immutable list

allSelectors is constant.

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

308-313: Make schema map constant

singleCustomGroupJsonSchema is also immutable.

-export let singleCustomGroupJsonSchema: Record<string, JSONSchema4> = {
+export const singleCustomGroupJsonSchema: Record<string, JSONSchema4> = {
   modifiers: buildCustomGroupModifiersJsonSchema(allModifiers),
   selector: buildCustomGroupSelectorJsonSchema(allSelectors),
   elementValuePattern: regexJsonSchema,
   elementNamePattern: regexJsonSchema,
 }
test/rules/sort-objects.test.ts (3)

1666-1685: Confirm 'multiline-member' is an allowed built-in group.

If this replaces legacy 'multiline', ensure the rule’s schema/types accept 'multiline-member' and both multiline properties and methods are matched. Optionally add a small valid/invalid pair covering a multiline method and a multiline property together to prove the selector.


4494-4513: Verify 'multiline-member' group in natural mode.

Double-check schema acceptance and that both multiline properties and methods fall under this group in natural sorting as well.


7321-7340: Verify 'multiline-member' group in line-length mode.

Same check as above to ensure parity across sort types.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 31585bd and 19eb203.

📒 Files selected for processing (10)
  • rules/sort-jsx-props.ts (0 hunks)
  • rules/sort-jsx-props/types.ts (3 hunks)
  • rules/sort-object-types.ts (1 hunks)
  • rules/sort-object-types/types.ts (1 hunks)
  • rules/sort-objects.ts (0 hunks)
  • rules/sort-objects/types.ts (3 hunks)
  • test/rules/sort-interfaces.test.ts (24 hunks)
  • test/rules/sort-jsx-props.test.ts (14 hunks)
  • test/rules/sort-object-types.test.ts (25 hunks)
  • test/rules/sort-objects.test.ts (9 hunks)
💤 Files with no reviewable changes (2)
  • rules/sort-objects.ts
  • rules/sort-jsx-props.ts
🧰 Additional context used
🧬 Code graph analysis (5)
rules/sort-object-types/types.ts (1)
types/join-with-dash.ts (1)
  • JoinWithDash (4-4)
rules/sort-object-types.ts (12)
rules/sort-object-types/types.ts (3)
  • SortObjectTypesSortingNode (383-391)
  • Selector (144-148)
  • Modifier (156-156)
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/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/get-custom-groups-compare-options.ts (1)
  • getCustomGroupsCompareOptions (93-124)
utils/report-all-errors.ts (1)
  • reportAllErrors (203-326)
test/rules/sort-jsx-props.test.ts (1)
test/utils/validate-rule-json-schema.ts (1)
  • validateRuleJsonSchema (8-19)
rules/sort-jsx-props/types.ts (4)
rules/sort-object-types/types.ts (2)
  • Selector (144-148)
  • allSelectors (334-339)
rules/sort-objects/types.ts (2)
  • Selector (157-157)
  • allSelectors (293-293)
rules/sort-exports/types.ts (2)
  • Selector (103-103)
  • allSelectors (139-139)
rules/sort-named-imports/types.ts (2)
  • Selector (109-109)
  • allSelectors (156-156)
rules/sort-objects/types.ts (2)
rules/sort-jsx-props/types.ts (2)
  • Selector (126-126)
  • allSelectors (155-155)
rules/sort-object-types/types.ts (2)
  • Selector (144-148)
  • allSelectors (334-339)
🪛 ESLint
test/rules/sort-interfaces.test.ts

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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


[error] 599-599: 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] 3235-3235: Unsafe use of a(n) error type typed template tag.

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)

test/rules/sort-objects.test.ts

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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)

test/rules/sort-object-types.test.ts

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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)

🔇 Additional comments (15)
test/rules/sort-interfaces.test.ts (5)

466-466: Group rename to optional-multiline-member is correct.

Renamed IDs align with the removal of legacy group names and keep expectations consistent.

Also applies to: 475-475, 489-489, 3136-3136, 3145-3145, 3160-3160, 5792-5792, 5801-5801, 5816-5816


552-583: Precedence test “index-signature over member” looks good across modes.

Solid coverage validating the new generic “member” bucket vs index signatures.

Also applies to: 3222-3253, 5878-5910


586-618: Precedence test “method over member” is correct and consistent.

Confirms “method” outranks the generic “member” group in all sorting types.

Also applies to: 3256-3287, 5912-5943


751-751: Use of multiline-member in customGroups and groups arrays is consistent.

The updates correctly reflect the new member-based grouping model.

Also applies to: 759-769, 806-807, 3421-3421, 3430-3430, 3439-3439, 3476-3476, 6076-6076, 6085-6085, 6094-6094, 6132-6132


489-489: Confirm schema/docs include new group IDs (member, multiline-member, optional-multiline-member).

Ensure JSON Schema, README, and rule docs list these identifiers to prevent config drift.

Also applies to: 751-751, 580-580

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

140-140: Confirm JoinWithDash yields intended group tokens

Please verify JoinWithDash<[ShorthandModifier, MultilineModifier, PropertySelector]> produces: 'prop' | 'shorthand-prop' | 'multiline-prop' | 'shorthand-multiline-prop' (and not require both modifiers nor alter token order).

If needed, I can add a tiny type-test file to assert these unions at build time.

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

203-205: LGTM: renamed groups to 'shorthand-prop'

The updates align with the new selector/modifier model and expected group identifiers.

Also applies to: 1590-1592, 2970-2971


307-309: LGTM: 'multiline-prop' group usage

Consistent with the new typings and grouping semantics.

Also applies to: 1694-1696, 3074-3075

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

1598-1629: Member grouping update looks correct (methods prioritized).

Test title, payload (leftGroup: 'member'), and groups: ['method', 'member'] align with the new selector semantics.


4426-4457: Member grouping update looks correct (methods prioritized).

Matches the alphabetical variant; payload and groups are consistent.


7253-7284: Member grouping update looks correct (methods prioritized).

Line-length variant mirrors the other suites; looks good.

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

239-241: Good: multiline is treated as a modifier only, and 'member' selector is always present.
This matches the new grouping model and avoids prior ambiguity.

Also applies to: 251-252

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

231-241: LGTM: PropertyGroup introduction aligns tests and rule semantics.

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

252-276: Group renames to 'member' and 'multiline-member' look correct.

Updates match the new Property/Member grouping model and align with rule/type changes.

Also applies to: 275-276, 2920-2950, 2953-2985, 5507-5573, 7988-7993


338-369: Sanity-check: precedence tests for index-signature/method over member.

Assertions and groups arrays correctly prefer 'index-signature' and 'method' over the generic 'member'.

If CI allows, re-run the suite focusing on these blocks to ensure no regressions in group resolution order.

Also applies to: 372-404, 2919-2950, 2953-2985, 5507-5573

memberProperty: something,
}
`,
code: dedent`
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 typescript/no-unsafe-call on dedent tagged templates.

ESLint flags the tagged calls because dedent’s types are any. Prefer a typed alternative.

Apply this import change (top of file):

-import dedent from 'dedent'
+import dedent from 'ts-dedent'

If switching packages is undesirable, alternatively cast once:

// near imports
import dedentUntyped from 'dedent'
const dedent: (s: TemplateStringsArray, ...v: unknown[]) => string =
  dedentUntyped as unknown as (s: TemplateStringsArray, ...v: unknown[]) => string

Or relax no-unsafe-call in test overrides, but code fix is preferred.

Also applies to: 4445-4445, 7272-7272

🧰 Tools
🪛 ESLint

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

(typescript/no-unsafe-call)

🤖 Prompt for AI Agents
In test/rules/sort-objects.test.ts around line 1617, ESLint flags the dedent
tagged template because dedent's types are any; replace the untyped import with
a typed alternative by updating the top-of-file import to a properly typed
dedent (or cast the imported dedent to the signature (s: TemplateStringsArray,
...v: unknown[]) => string) so the tagged template calls are typed and
no-unsafe-call errors are resolved; apply the same change for occurrences around
lines 4445 and 7272 if present.

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)
rules/sort-decorators.ts (1)

140-156: Handle TSParameterProperty in Decorator visitor (constructor parameter properties).

Visitor only matches decorator.parent.type === 'Identifier' (parent.parent.type === 'FunctionExpression') and will skip parameter properties wrapped in TSParameterProperty; detect TSParameterProperty (or unwrap .parameter) and call sortDecorators on its decorators so constructor/parameter-property decorators are sorted. Location: rules/sort-decorators.ts — Decorator visitor.

utils/compute-group.ts (1)

82-99: Deep‑flatten groups and filter strings only; current Set may miss nested groups or include config objects

options.groups supports nested arrays and non‑string config entries. Using flat() (depth 1) risks ignoring deeper groups and treating objects as valid entries, causing valid custom/predefined groups to be rejected. Build the lookup set by recursively collecting only string group names.

Apply:

-  // For lookup performance.
-  let groupsSet = new Set(options.groups.flat())
+  // For lookup performance: collect string group names from possibly nested arrays and ignore config objects.
+  const groupsSet = collectGroupNames(options.groups)
+
+  function collectGroupNames(groups: GroupsOptions<string>): Set<string> {
+    let set = new Set<string>()
+    let stack: unknown[] = [groups]
+    while (stack.length) {
+      let item = stack.pop() as unknown
+      if (Array.isArray(item)) {
+        for (let sub of item) stack.push(sub)
+      } else if (typeof item === 'string') {
+        set.add(item)
+      }
+      // ignore objects like { newlinesBetween: ... }
+    }
+    return set
+  }
test/rules/sort-imports.test.ts (1)

22-28: Restore spies after each test to prevent cross-test leakage

Some tests stub readClosestTsConfigByPath (and getTypescriptImport) but don’t always restore them. Add a global cleanup to avoid subtle pollution across cases and suites.

 describe('sort-imports', () => {
+  afterEach(() => {
+    vi.restoreAllMocks()
+  })
rules/sort-imports.ts (1)

354-369: Enable spacing errors: provide newlinesBetweenValueGetter.

Without it, ‘missed/extra spacing’ messages won’t fire.

   reportAllErrors<MessageId>({
     availableMessageIds: {
@@
     sortNodesExcludingEslintDisabled:
       createSortNodesExcludingEslintDisabled(sortingNodeGroups),
     sourceCode,
-    options,
+    options,
+    newlinesBetweenValueGetter: (left, right) =>
+      getLinesBetween(sourceCode, left, right),
     context,
     nodes,
   })

And import:

+import { getLinesBetween } from '../utils/get-lines-between'
test/rules/sort-interfaces.test.ts (2)

7909-7915: Remove deprecated ignorePattern from tests or update PR objectives/docs

PR intends to drop the deprecated ignorePattern, but tests/rules/docs still reference it — either keep the option and update the PR/docs, or migrate tests to a conditional unsorted config.

  • Fix this test: test/rules/sort-interfaces.test.ts:7911 — replace the options block with a conditional unsorted config, e.g. { useConfigurationIf: { declarationMatchesPattern: 'Ignore' }, type: 'unsorted' }.
  • Update or remove all other occurrences found in tests/rules/utils and docs (examples: test/rules/sort-objects.test.ts ~8784–8872, test/rules/sort-object-types.test.ts:7973, test/rules/sort-jsx-props.test.ts ~4270–4283, utils/get-settings.ts, test/utils/get-settings.test.ts, rules/*.ts, docs/content/**).

466-476: Standardize on "optional-multiline-member" — remove legacy "multiline-optional-member"

Code/tests already use "optional-multiline-member" (24 hits); the legacy alias "multiline-optional-member" appears only in docs: docs/content/rules/sort-interfaces.mdx:483 and docs/content/rules/sort-object-types.mdx:449 — remove/update those references and confirm schema/types/README list only "optional-multiline-member".

♻️ Duplicate comments (9)
rules/sort-jsx-props/types.ts (2)

106-111: Selector JSDoc is stale; only 'prop' is supported

Keep guidance aligned with the narrowed selector surface; use modifiers for shorthand/multiline.

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.
+   */

119-124: Clarify Selector doc to reflect narrowed surface

Document that specificity is via modifiers.

Apply:

-/**
- * 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 expressed via modifiers.
+ */
 export type Selector = PropertySelector
test/rules/sort-objects.test.ts (1)

1-7: Fix typescript/no-unsafe-call on dedent by using a typed alternative

Use ts-dedent (typed) to silence the rule without overrides.

Apply:

-import dedent from 'dedent'
+import dedent from 'ts-dedent'

Or, if keeping dedent:

import dedentUntyped from 'dedent'
const dedent: (s: TemplateStringsArray, ...v: unknown[]) => string =
  dedentUntyped as unknown as (s: TemplateStringsArray, ...v: unknown[]) => string

To verify and locate remaining imports:

#!/bin/bash
rg -nP "import\s+dedent\s+from\s+['\"]dedent['\"]" -C2
docs/content/rules/sort-heritage-clauses.mdx (5)

148-159: Fix copy: decorators → heritage clauses; make RegExpPattern.flags optional.

Still references decorators and requires flags. Apply:

 ### partitionByComment

 <sub>default: `false`</sub>

-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.
+- `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.
+- `{ block: boolean | RegExpPattern | RegExpPattern[]; line: boolean | RegExpPattern | RegExpPattern[] }` — Specify which block and line comments should act as delimiters.

168-176: Document full newlinesBetween union and semantics.

Align with implementation:

-<sub>type: `number | 'ignore'`</sub>
+<sub>type: `'ignore' | 'always' | 'never' | number`</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 newline errors.
+- `'always'` — Require exactly one blank line between groups.
+- `'never'` — Disallow blank lines between groups (equivalent to `0`).
+- `number` — Require exactly this number of blank lines between groups.

265-273: Expand CustomGroupDefinition types (‘custom’; newlinesInside union).

 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 }[]
 }

279-291: Unify CustomGroupAnyOfDefinition.fallbackSort type and mention selector.

 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' }
+  fallbackSort?: {
+    type: 'alphabetical' | 'natural' | 'line-length' | 'custom' | 'unsorted'
+    order?: 'asc' | 'desc'
+  }
   newlinesInside?: number
   anyOf: Array<{
-      selector?: string
+      selector?: string
       elementNamePattern?: string | string[] | { pattern: string; flags?: string } | { pattern: string; flags?: string }[]
   }>
 }

And document selector in Attributes (see next comment).


295-304: Document the ‘selector’ attribute.

 #### Attributes

 - `groupName` — The group's name, which needs to be put in the [`groups`](#groups) option.
+- `selector` — (AnyOf only) AST selector to narrow which elements the subgroup matches.
 - `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-object-types.ts (1)

341-349: Missing newlinesBetweenValueGetter → spacing diagnostics won’t trigger.

Pass a getter so missed/extra blank-line errors work.

   reportAllErrors<MessageIds>({
     sortNodesExcludingEslintDisabled,
+    newlinesBetweenValueGetter: (left, right) =>
+      getLinesBetween(sourceCode, left, right),
     availableMessageIds,
     sourceCode,
     options,
     context,
     nodes,
   })

Add import:

+import { getLinesBetween } from '../utils/get-lines-between'
🧹 Nitpick comments (33)
test/rules/sort-decorators.test.ts (2)

6-6: Lint: typescript/no-unsafe-call on tagged template (dedent).

Static analysis flags “unsafe call” on many dedent template tags. If this isn’t a false positive, ensure dedent is correctly typed:

  • Prefer ts-dedent (typed) or add @types/dedent.
  • Alternatively, add a small ambient type for tests.

Example ambient d.ts (tests only):

declare module 'dedent' {
  function dedent(strings: TemplateStringsArray, ...values: any[]): string
  export default dedent
}

6319-6327: Helper naming/intent.

duplicate5Times works, but a param for count would make it reusable across files (e.g., duplicateErrors(n, errors)).

rules/sort-decorators.ts (2)

49-67: Make defaults immutable and type‑checked at compile time.

Use const + satisfies to lock defaults to Required<Options[0]> and catch drift early.

-let defaultOptions: Required<Options[0]> = {
+const defaultOptions = {
   fallbackSort: { type: 'unsorted' },
   specialCharacters: 'keep',
   partitionByComment: false,
   partitionByNewLine: false,
   newlinesBetween: 'ignore',
   sortOnProperties: true,
   sortOnParameters: true,
   sortOnAccessors: true,
   type: 'alphabetical',
   sortOnClasses: true,
   sortOnMethods: true,
   ignoreCase: true,
   customGroups: [],
   locales: 'en-US',
   alphabet: '',
   order: 'asc',
   groups: [],
-}
+} satisfies Required<Options[0]>

4-7: Combine type/value imports from types module.

Minor import tidy to reduce duplication.

-import type {
-  SortDecoratorsSortingNode,
-  Options,
-} from './sort-decorators/types'
-
-import { singleCustomGroupJsonSchema } from './sort-decorators/types'
+import {
+  type SortDecoratorsSortingNode,
+  type Options,
+  singleCustomGroupJsonSchema,
+} from './sort-decorators/types'

Also applies to: 30-30

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

52-58: API shape looks solid; small typing cleanup suggestion.

  • customGroups extension with fallbackSort.sortBy is clear and consistent.
  • Suggest narrowing IndexSignatureGroup to just 'index-signature' (index signatures have no modifiers per AllowedModifiersPerSelector), to avoid permitting unattainable groups like required-index-signature. This keeps type-level guidance tight.

Also applies to: 228-238

utils/get-newlines-between-option.ts (1)

25-30: LGTM on requiring customGroups; behavior matches same-group newlinesInside.

Consider precomputing a name→customGroup map at caller level if this runs in tight loops, but not blocking.

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

370-383: Update docs: reflect new customGroups API, remove deprecated options, fix test link

  • Replace the customGroups type doc that currently shows { [groupName: string]: string | string[] } with the array-of-objects shape (or reference CustomGroupsOption) in docs/content/rules/sort-objects.mdx (example config area ≈ lines 363–402).
  • Remove deprecated options (e.g., ignorePattern, destructureOnly) from the canonical Usage/config snippets so examples match the current API.
  • Fix the Resources "Test source" link in docs/content/rules/sort-objects.mdx — it currently points to test/sort-objects.test.ts; update to test/rules/sort-objects.test.ts (the actual test file is test/rules/sort-objects.test.ts).
test/utils/get-newlines-between-option.test.ts (1)

380-387: Nit: tighten helper contract docs and naming

Now that customGroups defaults to an array, the helper effectively always supplies an array. Consider reflecting that in the test descriptions to avoid implying “undefined”.

Apply this diff to update the description that still mentions “not defined”:

-      'should return the global option (`%s`) if "customGroups" is not defined',
+      'should return the global option (`%s`) when "customGroups" is empty or omitted',
utils/get-newlines-between-errors.ts (1)

48-50: Docstring says “Optional” but the type is required

The property is non‑optional in the type. Make the JSDoc consistent.

Apply this diff:

-    /** Optional custom groups configuration. */
-    customGroups: CustomGroupsOption
+    /** Custom groups configuration (required). */
+    customGroups: CustomGroupsOption
utils/make-newlines-between-fixes.ts (1)

29-30: Docstring says “Optional” but the type is required

Align JSDoc with the signature.

Apply this diff:

-    /** Optional custom groups configuration. */
-    customGroups: CustomGroupsOption
+    /** Custom groups configuration (required). */
+    customGroups: CustomGroupsOption
test/rules/sort-object-types.test.ts (3)

338-367: “member” fallback precedence: add one positive (valid) case

You exercised “index-signature over member”. Add a simple valid case proving a plain property falls into member and stays after the specific group. This guards regressions in the fallback classifier.

Also applies to: 2849-2880, 5367-5398


372-403: “method over member”: assert adjacency (no unintended blank lines)

Current tests check order only. Add one valid case asserting no spacing change occurs when both are same partition and newlinesBetween doesn’t mandate separation.

Also applies to: 2883-2914, 5402-5433


2110-2238: Config precedence with multiple useConfigurationIf blocks

Nice coverage. Consider an extra test where both blocks match to assert precedence is by array order (first match wins). This will document and lock expected behavior.

Also applies to: 4721-4749, 7232-7260

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

303-305: Fix regex precedence in allNamesMatchPattern.

'^r|g|b$' matches strings starting with 'r' OR containing 'g' OR ending with 'b'. Use '^(r|g|b)$' (or '^[rgb]$') to match exactly r, g, or b.

Apply this diff:

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

484-492: Tighten the “callback” example pattern.

'^on.+' also matches 'one'/'only'. Prefer '^on[A-Z].*' for React-style event handlers.

Apply this diff:

-      elementNamePattern: '^on.+'
+      elementNamePattern: '^on[A-Z].*'

245-255: Document missing newlinesBetween values ('always' | 'never').

Types allow 'always' and 'never', but docs list only 'ignore' | number. Add both and brief semantics.

Apply this diff:

-<sub>type: `number | 'ignore'`</sub>
+<sub>type: `'ignore' | 'always' | 'never' | number`</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'` — Preserve current spacing (no fixes).
+- `'always'` — Enforce exactly one blank line between groups.
+- `'never'` — Disallow blank lines between groups.
+- `0` — Alias of `'never'`.
+- Any other number — Enforce that exact number of blank lines between groups; forbid newlines inside groups.

221-237: Incorrect type/description for [DEPRECATED] ignorePattern.

This section shows an object with allNamesMatchPattern, which belongs to useConfigurationIf, not ignorePattern. For this rule, ignorePattern matches the JSX tag name (string | regex | arrays).

Apply this diff:

-<sub>
-  type:
-  ```
-  {
-    allNamesMatchPattern?: string | string[] | { pattern: string; flags: string } | { pattern: string; flags: string }[]
-  }
-  ```
-</sub>
-<sub>default: `[]`</sub>
-
-Use the [useConfigurationIf.tagMatchesPattern](#useconfigurationif) option alongside [type: unsorted](#type) instead.
-
-Specifies names or patterns for JSX elements that should be ignored by this rule. This can be useful if you have specific components that you do not want to sort.
+<sub>
+  type: `string | string[] | { pattern: string; flags?: string } | { pattern: string; flags?: string }[]`
+</sub>
+<sub>default: `[]`</sub>
+
+Deprecated. Prefer `useConfigurationIf.tagMatchesPattern` with `type: 'unsorted'`.
+
+Specifies tag names or patterns for JSX elements to ignore (skip sorting).

422-434: Allow 'always' | 'never' for newlinesInside in interfaces.

Types support 'always' | 'never' | number, but docs list only number.

Apply this diff:

-  newlinesInside?: number
+  newlinesInside?: 'always' | 'never' | number

Also applies to: 440-453


575-576: Update “Resources” links to new locations.

Tests moved under test/rules with Vitest. Update links to avoid 404/old paths.

Apply this diff:

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

If the path differs (e.g., tests/ vs test/), adjust accordingly.

utils/get-comment-above-that-should-exist.ts (2)

17-22: Docstring says “Optional” but property is now required.

Update the comment to avoid confusion.

Apply this diff:

-    /** Optional custom groups configuration. */
+    /** Custom groups configuration. */
     customGroups: CustomGroupsOption

94-99: Guard when rightGroupIndex is 0; avoid non-null assertion and negative index.

When rightGroupIndex === 0, groups[-1] yields undefined. The ! is misleading even if guarded later. Early-return for index 0 and remove the assertion.

Apply this diff:

-  let groupAboveRight = options.groups[rightGroupIndex - 1]!
+  if (rightGroupIndex === 0) {
+    return null
+  }
+  let groupAboveRight = options.groups[rightGroupIndex - 1]
   if (!isCommentAboveOption(groupAboveRight)) {
     return null
   }
@@
-  return {
-    comment: groupAboveRight.commentAbove,
+  return {
+    comment: groupAboveRight.commentAbove,
     exists: !!matchingCommentsAbove,
   }

Also applies to: 106-109, 111-113

utils/make-fixes.ts (1)

138-154: Skip newlines computation when it’s a no-op.

Micro-optimization: avoid calling makeNewlinesBetweenFixes when global newlinesBetween is 'ignore' and there are no per-group overrides.

Apply this diff:

-  if (options?.groups) {
+  if (options?.groups) {
+    const hasGroupOverrides =
+      options.groups.some(g => typeof g === 'object' && 'newlinesBetween' in g)
+    if (options.newlinesBetween === 'ignore' && !hasGroupOverrides) {
+      // No spacing work needed
+    } else {
       let newlinesFixes = makeNewlinesBetweenFixes({
         options: {
           ...options,
           newlinesBetween: options.newlinesBetween,
           groups: options.groups,
         },
         newlinesBetweenValueGetter,
         sortedNodes,
         sourceCode,
         fixer,
         nodes,
       })
       if (newlinesFixes.length > 0) {
         return [...orderFixes, ...newlinesFixes]
       }
+    }
   }
rules/sort-jsx-props.ts (1)

44-46: Module-level cache lifecycle.

Minor: cachedGroupsByModifiersAndSelectors is module-scoped and persists across files/runs. Consider clearing it per rule invocation (e.g., in create) to avoid unbounded growth across diverse modifier/selector combos (low risk here).

utils/validate-generated-groups-configuration.ts (1)

9-11: Also validate duplicate custom group names.

We validate duplicate groups, but not duplicate customGroups.groupName entries. Add a quick check to prevent ambiguous resolution.

Apply this diff:

 export function validateGeneratedGroupsConfiguration({
   selectors,
   modifiers,
   options,
 }: ValidateGenerateGroupsConfigurationParameters): void {
-  let availableCustomGroupNames = new Set(
-    options.customGroups.map(customGroup => customGroup.groupName),
-  )
+  const customNames = options.customGroups.map(cg => cg.groupName)
+  const dupCustom = customNames.filter(
+    (n, i) => customNames.indexOf(n) !== i,
+  )
+  if (dupCustom.length > 0) {
+    throw new Error(`Duplicated custom group(s): ${Array.from(new Set(dupCustom)).join(', ')}`)
+  }
+  let availableCustomGroupNames = new Set(customNames)

Also applies to: 79-81, 83-91

utils/compute-group.ts (1)

55-66: JSDoc example still references removed “name” param

The param was dropped; example should not include it.

Apply:

- *     predefinedGroups: ['external'],
- *     name: 'react-dom',
+ *     predefinedGroups: ['external'],
rules/sort-object-types.ts (1)

247-251: Don’t assign optional/required to TSIndexSignature.

Index signatures aren’t optional/required; current logic misclassifies them.

-    if (isMemberOptional(typeElement)) {
-      modifiers.push('optional')
-    } else {
-      modifiers.push('required')
-    }
+    if (typeElement.type !== 'TSIndexSignature') {
+      if (isMemberOptional(typeElement)) {
+        modifiers.push('optional')
+      } else {
+        modifiers.push('required')
+      }
+    }
rules/sort-heritage-clauses.ts (1)

150-160: Set correct partitionId when pushing.

Currently all nodes use 0. Assign the partition index on push.

-    let sortingNode: SortingNode = {
+    let sortingNode: Omit<SortingNode, 'partitionId'> = {
       isEslintDisabled: isNodeEslintDisabled(
@@
-      partitionId: 0,
       group,
       name,
     }
@@
-    formattedMembers.at(-1)!.push(sortingNode)
+    formattedMembers.at(-1)!.push({
+      ...sortingNode,
+      partitionId: formattedMembers.length,
+    })

Also applies to: 174-175

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

11-15: Use const for tester destructuring

No reassignment; prefer const.

-  let { invalid, valid } = createRuleTester({
+  const { invalid, valid } = createRuleTester({
     parser: typescriptParser,
     name: 'sort-interfaces',
     rule,
   })

17-23: Prefer const for immutable options

You already assert as const; declare with const.

-    let options = {
+    const options = {
       type: 'alphabetical',
       order: 'asc',
     } as const

Repeat in other describe blocks for consistency.


552-584: Coverage for index-signature > member precedence looks solid

Nice focused assertions and autofix outputs.

Consider adding one triad test showing full ordering in a single interface: index-signature → method → member, with groups: ['index-signature','method','member'].

Also applies to: 3127-3159, 5688-5720


586-618: Method > member precedence validated; unify sample literal quoting

Outputs mix 'something' and "something". Not wrong, but uniform quotes reduce noise in snapshots.

Also applies to: 3161-3193, 5722-5754


2318-2349: Great addition: conditional configs via useConfigurationIf + allNamesMatchPattern

Consider one extra case to assert fallback selection when none of the conditional configs match (proves default branch is applied).

Also applies to: 4896-4924, 7450-7478


7-7: Use public export for Alphabet in tests (if available)
To exercise published API, import from the package’s ./alphabet export instead of an internal path (keep as-is if tests run purely against sources).

-import { Alphabet } from '../../utils/alphabet'
+import { Alphabet } from '../../alphabet'
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 19eb203 and 3d58205.

📒 Files selected for processing (43)
  • docs/content/rules/sort-heritage-clauses.mdx (5 hunks)
  • docs/content/rules/sort-interfaces.mdx (1 hunks)
  • docs/content/rules/sort-jsx-props.mdx (3 hunks)
  • docs/content/rules/sort-object-types.mdx (1 hunks)
  • docs/content/rules/sort-objects.mdx (1 hunks)
  • rules/sort-decorators.ts (5 hunks)
  • rules/sort-decorators/types.ts (1 hunks)
  • rules/sort-enums.ts (2 hunks)
  • rules/sort-heritage-clauses.ts (5 hunks)
  • rules/sort-heritage-clauses/types.ts (1 hunks)
  • rules/sort-imports.ts (6 hunks)
  • rules/sort-imports/types.ts (1 hunks)
  • rules/sort-interfaces.ts (1 hunks)
  • rules/sort-jsx-props.ts (2 hunks)
  • rules/sort-jsx-props/types.ts (4 hunks)
  • rules/sort-object-types.ts (3 hunks)
  • rules/sort-object-types/get-custom-groups-compare-options.ts (1 hunks)
  • rules/sort-object-types/types.ts (2 hunks)
  • rules/sort-objects.ts (2 hunks)
  • rules/sort-objects/types.ts (4 hunks)
  • test/rules/sort-decorators.test.ts (2 hunks)
  • test/rules/sort-heritage-clauses.test.ts (5 hunks)
  • test/rules/sort-imports.test.ts (24 hunks)
  • test/rules/sort-interfaces.test.ts (15 hunks)
  • test/rules/sort-jsx-props.test.ts (35 hunks)
  • test/rules/sort-object-types.test.ts (18 hunks)
  • test/rules/sort-object-types/get-custom-groups-compare-options.test.ts (0 hunks)
  • test/rules/sort-objects.test.ts (29 hunks)
  • test/utils/compute-group.test.ts (3 hunks)
  • test/utils/get-custom-groups-compare-options.test.ts (0 hunks)
  • test/utils/get-newlines-between-option.test.ts (4 hunks)
  • types/common-options.ts (0 hunks)
  • utils/common-json-schemas.ts (0 hunks)
  • utils/compute-group.ts (4 hunks)
  • utils/get-comment-above-that-should-exist.ts (2 hunks)
  • utils/get-custom-groups-compare-options.ts (2 hunks)
  • utils/get-newlines-between-errors.ts (1 hunks)
  • utils/get-newlines-between-option.ts (1 hunks)
  • utils/make-comment-above-fixes.ts (2 hunks)
  • utils/make-fixes.ts (2 hunks)
  • utils/make-newlines-between-fixes.ts (1 hunks)
  • utils/report-all-errors.ts (0 hunks)
  • utils/validate-generated-groups-configuration.ts (5 hunks)
💤 Files with no reviewable changes (5)
  • utils/report-all-errors.ts
  • test/utils/get-custom-groups-compare-options.test.ts
  • test/rules/sort-object-types/get-custom-groups-compare-options.test.ts
  • utils/common-json-schemas.ts
  • types/common-options.ts
🚧 Files skipped from review as they are similar to previous changes (6)
  • docs/content/rules/sort-interfaces.mdx
  • docs/content/rules/sort-object-types.mdx
  • rules/sort-interfaces.ts
  • rules/sort-decorators/types.ts
  • rules/sort-heritage-clauses/types.ts
  • rules/sort-objects/types.ts
🧰 Additional context used
🧬 Code graph analysis (19)
utils/get-newlines-between-option.ts (1)
types/common-options.ts (1)
  • CustomGroupsOption (103-140)
utils/get-custom-groups-compare-options.ts (1)
types/common-options.ts (1)
  • CustomGroupsOption (103-140)
utils/make-comment-above-fixes.ts (1)
types/common-options.ts (1)
  • CustomGroupsOption (103-140)
utils/make-fixes.ts (1)
types/common-options.ts (3)
  • NewlinesBetweenOption (203-226)
  • CustomGroupsOption (103-140)
  • GroupsOptions (445-451)
utils/get-newlines-between-errors.ts (1)
types/common-options.ts (1)
  • CustomGroupsOption (103-140)
utils/compute-group.ts (2)
types/common-options.ts (1)
  • CustomGroupsOption (103-140)
rules/sort-imports/types.ts (1)
  • SingleCustomGroup (182-194)
rules/sort-imports/types.ts (1)
types/common-options.ts (1)
  • CustomGroupsOption (103-140)
utils/get-comment-above-that-should-exist.ts (1)
types/common-options.ts (1)
  • CustomGroupsOption (103-140)
rules/sort-jsx-props.ts (1)
utils/common-json-schemas.ts (1)
  • buildCustomGroupsArrayJsonSchema (302-351)
rules/sort-enums.ts (1)
utils/common-json-schemas.ts (1)
  • buildCustomGroupsArrayJsonSchema (302-351)
rules/sort-object-types/types.ts (3)
types/common-options.ts (2)
  • CustomGroupsOption (103-140)
  • FallbackSortOption (319-331)
rules/sort-objects/types.ts (1)
  • SingleCustomGroup (122-138)
types/join-with-dash.ts (1)
  • JoinWithDash (4-4)
rules/sort-objects.ts (1)
utils/common-json-schemas.ts (1)
  • buildCustomGroupsArrayJsonSchema (302-351)
rules/sort-object-types.ts (12)
utils/common-json-schemas.ts (1)
  • buildCustomGroupsArrayJsonSchema (302-351)
rules/sort-object-types/types.ts (4)
  • sortByJsonSchema (350-353)
  • SortObjectTypesSortingNode (380-388)
  • Selector (141-145)
  • Modifier (153-153)
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/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-72)
utils/get-custom-groups-compare-options.ts (1)
  • getCustomGroupsCompareOptions (89-118)
utils/report-all-errors.ts (1)
  • reportAllErrors (203-325)
utils/validate-generated-groups-configuration.ts (1)
types/common-options.ts (1)
  • CustomGroupsOption (103-140)
rules/sort-decorators.ts (10)
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/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/does-custom-group-match.ts (1)
  • doesCustomGroupMatch (121-141)
utils/get-custom-groups-compare-options.ts (1)
  • buildGetCustomGroupOverriddenOptionsFunction (137-148)
rules/sort-heritage-clauses.ts (10)
rules/sort-heritage-clauses/types.ts (1)
  • Options (14-22)
utils/common-json-schemas.ts (5)
  • buildCustomGroupsArrayJsonSchema (302-351)
  • partitionByNewLineJsonSchema (268-272)
  • partitionByCommentJsonSchema (241-262)
  • 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/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/types.ts (2)
types/common-options.ts (1)
  • CustomGroupsOption (103-140)
rules/sort-exports/types.ts (3)
  • SingleCustomGroup (72-91)
  • Selector (103-103)
  • allSelectors (139-139)
utils/make-newlines-between-fixes.ts (1)
types/common-options.ts (2)
  • NewlinesBetweenOption (203-226)
  • CustomGroupsOption (103-140)
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)
🪛 ESLint
test/rules/sort-interfaces.test.ts

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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


[error] 599-599: 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] 3140-3140: Unsafe use of a(n) error type typed template tag.

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)

test/rules/sort-object-types.test.ts

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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)

test/rules/sort-decorators.test.ts

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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


[error] 1046-1046: 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] 1106-1106: Unsafe use of a(n) error type typed template tag.

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


[error] 1397-1397: 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] 1414-1414: Unsafe use of a(n) error type typed template tag.

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)

test/rules/sort-objects.test.ts

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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)

test/rules/sort-heritage-clauses.test.ts

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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


[error] 986-986: 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] 1035-1035: Unsafe use of a(n) error type typed template tag.

(typescript/no-unsafe-call)


[error] 1074-1074: 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] 1109-1109: Unsafe use of a(n) error type typed template tag.

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)

test/rules/sort-imports.test.ts

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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)

Comment on lines +192 to 206
reportAllErrors<MessageId>({
availableMessageIds: {
missedSpacingBetweenMembers: 'missedSpacingBetweenHeritageClauses',
extraSpacingBetweenMembers: 'extraSpacingBetweenHeritageClauses',
unexpectedGroupOrder: 'unexpectedHeritageClausesGroupOrder',
unexpectedOrder: 'unexpectedHeritageClausesOrder',
},
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

Provide newlinesBetweenValueGetter to report spacing errors.

   reportAllErrors<MessageId>({
     availableMessageIds: {
@@
-      sourceCode,
-      options,
+      sourceCode,
+      options,
+      newlinesBetweenValueGetter: (left, right) =>
+        getLinesBetween(sourceCode, left, right),
       context,
       nodes,
     })

And import:

+import { getLinesBetween } from '../utils/get-lines-between'
📝 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
reportAllErrors<MessageId>({
availableMessageIds: {
missedSpacingBetweenMembers: 'missedSpacingBetweenHeritageClauses',
extraSpacingBetweenMembers: 'extraSpacingBetweenHeritageClauses',
unexpectedGroupOrder: 'unexpectedHeritageClausesGroupOrder',
unexpectedOrder: 'unexpectedHeritageClausesOrder',
},
sortNodesExcludingEslintDisabled:
createSortNodesExcludingEslintDisabled(nodes),
sourceCode,
options,
context,
nodes,
})
import { getLinesBetween } from '../utils/get-lines-between'
reportAllErrors<MessageId>({
availableMessageIds: {
missedSpacingBetweenMembers: 'missedSpacingBetweenHeritageClauses',
extraSpacingBetweenMembers: 'extraSpacingBetweenHeritageClauses',
unexpectedGroupOrder: 'unexpectedHeritageClausesGroupOrder',
unexpectedOrder: 'unexpectedHeritageClausesOrder',
},
sortNodesExcludingEslintDisabled:
createSortNodesExcludingEslintDisabled(nodes),
sourceCode,
options,
newlinesBetweenValueGetter: (left, right) =>
getLinesBetween(sourceCode, left, right),
context,
nodes,
})
🤖 Prompt for AI Agents
In rules/sort-heritage-clauses.ts around lines 192-205, the call to
reportAllErrors is missing the newlinesBetweenValueGetter option; add
newlinesBetweenValueGetter: newlinesBetweenValueGetter to the object passed into
reportAllErrors so spacing errors are reported, and add an import for
newlinesBetweenValueGetter from the utility module where other value getters
live (import newlinesBetweenValueGetter from the appropriate utils path at the
top of the file).

},
it('handles hash symbol in internal patterns correctly', async () => {
await valid({
code: dedent`
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

⚠️ Potential issue

Fix ESLint no-unsafe-call on dedent tagged templates (newly added lines)

Static analysis flags the tagged use of dedent here. Quick unblock: locally disable the rule for these lines. Longer-term, consider switching the tests to ts-dedent (typed) or using dedent(String.raw\...`) across the suite.

-        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`

Also applies to: 4349-4349, 4361-4361

🧰 Tools
🪛 ESLint

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

(typescript/no-unsafe-call)

🤖 Prompt for AI Agents
In test/rules/sort-imports.test.ts around lines 4312, 4349, and 4361, ESLint
flags the tagged use of `dedent` as a no-unsafe-call; to quickly unblock tests,
add a local ESLint disable comment immediately before each offending line to
silence @typescript-eslint/no-unsafe-call for that single line (i.e., use an
eslint-disable-next-line for that rule), run the linter to confirm only those
lines are suppressed, and consider the longer-term alternatives noted in the
comment (ts-dedent or dedent(String.raw`...`).

Comment on lines +29 to 36
newlinesBetween: NewlinesBetweenOption

/** Custom groups configuration for advanced grouping. */
customGroups: CustomGroupsOption

/** Groups configuration defining available groups and their order. */
groups?: GroupsOptions<string>
groups: GroupsOptions<string>
}
Copy link

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

Required fields inside an optional options object.

newlinesBetween, customGroups, and groups are required but options itself is optional. Verify all callers always pass options with these fields; otherwise, make options required.


🏁 Script executed:

#!/bin/bash
# List all invocations to ensure `options` is provided.
rg -nP "makeFixes\s*\(" -C3

Length of output: 1312


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== make-fixes.ts (1-220) ==="
nl -ba utils/make-fixes.ts | sed -n '1,220p' || true

echo "=== make-fixes.ts (220-480) ==="
nl -ba utils/make-fixes.ts | sed -n '220,480p' || true

echo "=== makeFixes call sites ==="
rg -nP "makeFixes\\s*\\(" -C3 || true

echo "=== utils/report-errors.ts (120-160) ==="
nl -ba utils/report-errors.ts | sed -n '120,160p' || true

echo "=== rules/sort-switch-case.ts (240-280) ==="
nl -ba rules/sort-switch-case.ts | sed -n '240,280p' || true

Length of output: 1654


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== locate makeFixes definition ==="
rg -nP "export\s+(?:const|function)\s+makeFixes|const\s+makeFixes\s*[:=]|function\s+makeFixes\s*\(" --hidden || true

echo
echo "=== show make-fixes.ts (full) with line numbers ==="
awk '{printf "%5d: %s\n", NR, $0}' utils/make-fixes.ts || true

echo
echo "=== show call sites for makeFixes with context ==="
rg -nP "makeFixes\\s*\\(" -n -C8 || true

echo
echo "=== utils/report-errors.ts (110-160) ==="
awk 'NR>=110 && NR<=160{printf "%5d: %s\n", NR, $0}' utils/report-errors.ts || true

echo
echo "=== rules/sort-switch-case.ts (240-280) ==="
awk 'NR>=240 && NR<=280{printf "%5d: %s\n", NR, $0}' rules/sort-switch-case.ts || true

Length of output: 13066


Make nested fields in MakeFixesParameters optional or require callers to always pass options.

A call site omits options (rules/sort-switch-case.ts — makeFixes at ~254–260), while MakeFixesParameters declares options?: { newlinesBetween: NewlinesBetweenOption; customGroups: CustomGroupsOption; groups: GroupsOptions } (utils/make-fixes.ts). Either:

  • Preferred: mark newlinesBetween, customGroups, groups as optional in utils/make-fixes.ts; or
  • Alternative: make options required and update all callers to pass a complete options object (e.g., rules/sort-switch-case.ts and utils/report-errors.ts).
🤖 Prompt for AI Agents
In utils/make-fixes.ts around lines 29–36, the nested fields inside the optional
options object are currently required which causes call sites that omit options
to fail; change the declaration so newlinesBetween, customGroups, and groups are
optional (e.g., add ? to each field or replace the options type with
Partial<...>) so callers can omit the entire options object, and update any
dependent types/usages if necessary; alternatively, if you choose the other
approach, make the top-level options required and update all callers
(rules/sort-switch-case.ts and utils/report-errors.ts) to pass a complete
options object.

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 (8)
rules/sort-object-types/types.ts (1)

225-233: Index signatures can’t be optional/required — simplify IndexSignatureGroup

The current JoinWithDash includes Optional/Required/Multiline for index-signature, which are invalid. Restrict the group type to the selector only.

Apply:

-type IndexSignatureGroup = JoinWithDash<
-  [
-    OptionalModifier,
-    RequiredModifier,
-    MultilineModifier,
-    IndexSignatureSelector,
-  ]
->
+type IndexSignatureGroup = JoinWithDash<[IndexSignatureSelector]>
rules/sort-interfaces.ts (1)

20-36: Drop deprecated ignorePattern from v5 (types, defaults, schema, code, docs, tests).

ignorePattern remains in defaults/types/schema/implementation/docs/tests and must be removed or replaced by the new configuration approach (e.g., useConfigurationIf.*).

Files/locations found (action required):

  • utils/get-settings.ts (+ test: test/utils/get-settings.test.ts)
  • rules/sort-interfaces.ts (defaultOptions)
  • rules/sort-objects.ts (defaultOptions, usage: matches(..., options.ignorePattern), jsonSchema)
  • rules/sort-object-types.ts (defaultOptions, usage, jsonSchema)
  • rules/sort-object-types/types.ts
  • rules/sort-objects/types.ts
  • rules/sort-jsx-props.ts (defaultOptions, usage, jsonSchema)
  • rules/sort-jsx-props/types.ts
  • docs/content/guide/getting-started.mdx
  • docs/content/rules/*.mdx (sort-object-types, sort-jsx-props, sort-objects, sort-interfaces)
  • tests referencing ignorePattern under test/rules/*

Required changes:

  • Remove ignorePattern from all Option type definitions.
  • Remove ignorePattern from JSON schemas (drop regexJsonSchema entries).
  • Remove from defaultOptions in all rules.
  • Refactor code that reads options.ignorePattern (matches(...) checks) to use the intended v5 mechanism (useConfigurationIf.*) or equivalent logic.
  • Update/remove tests that assert ignorePattern behavior.
  • Update docs and add migration notes for v5.
rules/sort-maps.ts (1)

249-258: String-literal Map keys are returned with quotes; this breaks pattern matching.

getNodeName uses Literal.raw (""foo""), so allNamesMatchPattern/customGroups won’t match '^foo$'. Use Literal.value when it’s a string.

   if (element.type === 'ArrayExpression') {
     let [left] = element.elements

     if (!left) {
       return `${left}`
-    } else if (left.type === 'Literal') {
-      return left.raw
+    } else if (left.type === 'Literal') {
+      // Prefer unquoted value for string literals; fall back to raw otherwise.
+      // @ts-expect-error TS narrows value on Literal
+      return typeof left.value === 'string' ? String(left.value) : left.raw
     }
     return sourceCode.getText(left)
   }
docs/content/rules/sort-objects.mdx (1)

575-579: customGroups type is outdated; docs show deprecated shape.

The page says the object-based API is deprecated but the type still documents it. Switch to the array-based definitions, consistent with other pages.

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

336-340: Partition ID off-by-one can merge partitions during sort.

partitionId is 1-based (length) while partitions are 0-based indices (last bucket at length - 1). This can allow cross-partition reordering in downstream sorting.

Use the current bucket index:

-            accumulator.at(-1)!.push({
+            accumulator.at(-1)!.push({
               ...sortingNode,
-              partitionId: accumulator.length,
+              partitionId: accumulator.length - 1,
             })
rules/sort-jsx-props.ts (3)

55-69: v5 target: remove deprecated ignorePattern from defaults.

Per the v5 goals, drop ignorePattern from defaultOptions.

 let defaultOptions: Required<Options[number]> = {
   fallbackSort: { type: 'unsorted' },
   specialCharacters: 'keep',
   newlinesBetween: 'ignore',
   partitionByNewLine: false,
   useConfigurationIf: {},
   type: 'alphabetical',
-  ignorePattern: [],
   ignoreCase: true,
   customGroups: [],
   locales: 'en-US',
   alphabet: '',
   order: 'asc',
   groups: [],
 }

95-101: Remove runtime support for ignorePattern.

Eliminate the deprecated ignorePattern branch and rely on useConfigurationIf.tagMatchesPattern only.

-      let shouldIgnore = matches(
-        sourceCode.getText(node.openingElement.name),
-        options.ignorePattern,
-      )
-      if (shouldIgnore || !isSortable(node.openingElement.attributes)) {
-        return
-      }
+      // ignorePattern removed in v5

216-233: Schema still exposes deprecated ignorePattern.

Drop ignorePattern from the public JSON schema for this rule.

         properties: {
           ...commonJsonSchemas,
           useConfigurationIf: buildUseConfigurationIfJsonSchema({
             additionalProperties: {
               tagMatchesPattern: regexJsonSchema,
             },
           }),
           customGroups: buildCustomGroupsArrayJsonSchema({
             singleCustomGroupJsonSchema,
           }),
           partitionByNewLine: partitionByNewLineJsonSchema,
           newlinesBetween: newlinesBetweenJsonSchema,
-          ignorePattern: regexJsonSchema,
           groups: groupsJsonSchema,
         },
♻️ Duplicate comments (5)
test/rules/sort-imports.test.ts (1)

4312-4312: Fix ESLint no-unsafe-call for new dedent tagged templates

Silence the rule locally for these new lines to unblock CI. Longer term: consider ts-dedent or dedent(String.raw\...`) across tests.

         await valid({
-        code: dedent`
+        // eslint-disable-next-line @typescript-eslint/no-unsafe-call
+        code: dedent`
...
         await invalid({
-        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`

Also applies to: 4349-4349, 4361-4361

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

192-205: Pass newlinesBetweenValueGetter to enable spacing diagnostics.

Without it, spacing errors may be missed. Add the getter and import getLinesBetween.

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

4-4: Fix typescript/no-unsafe-call on dedent import.

Use a typed dedent to satisfy ESLint. This single import change fixes all flagged tagged-template calls in this file.

-import dedent from 'dedent'
+import dedent from 'ts-dedent'
rules/sort-object-types.ts (2)

240-244: Don’t assign optional/required to index signatures.

Index signatures don’t have optionality; assigning required/optional produces misleading groups.

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

334-343: Enable spacing diagnostics for object types.

Pass newlinesBetweenValueGetter to support missed/extra blank-line errors when newlinesBetween is configured.

+import { getLinesBetween } from '../utils/get-lines-between'
@@
   reportAllErrors<MessageIds>({
     sortNodesExcludingEslintDisabled,
     availableMessageIds,
     sourceCode,
+    newlinesBetweenValueGetter: (left, right) =>
+      getLinesBetween(sourceCode, left, right),
     options,
     context,
     nodes,
   })

Also applies to: 1-22

🧹 Nitpick comments (27)
rules/sort-intersection-types.ts (1)

20-33: Prefer const + satisfies for immutability and tighter typing

Use const and the satisfies operator to keep literals narrow and enable better DCE/treeshaking. No runtime change.

Apply:

-let defaultOptions: Required<Options[number]> = {
+const defaultOptions = {
   fallbackSort: { type: 'unsorted' },
   specialCharacters: 'keep',
   newlinesBetween: 'ignore',
   partitionByComment: false,
   partitionByNewLine: false,
   type: 'alphabetical',
   ignoreCase: true,
   locales: 'en-US',
   customGroups: [],
   alphabet: '',
   order: 'asc',
   groups: [],
-}
+} satisfies Required<Options[number]>;
rules/sort-switch-case.ts (1)

30-38: Prefer const for immutable defaults

defaultOptions isn’t reassigned. Using const prevents accidental mutation.

Apply:

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

50-63: Make defaults immutable

Use const to guard against reassignment.

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

50-63: Use const for defaultOptions

Minor immutability/readability win.

-let defaultOptions: Required<Options[number]> = {
+const defaultOptions: Required<Options[number]> = {
utils/filter-options-by-all-names-match.ts (1)

80-94: Logic is sound; clarify empty inputs behavior

Current logic treats empty nodeNames as matching (vacuous truth). If that’s intended, great; if not, add an explicit guard.

Option if you want “no names ⇒ no conditional match”:

 export function filterOptionsByAllNamesMatch<T extends Options>({
   contextOptions,
   nodeNames,
 }: {
   contextOptions: T[]
   nodeNames: string[]
 }): T[] {
-  return contextOptions.filter(options => {
+  if (nodeNames.length === 0) return contextOptions
+  return contextOptions.filter(options => {
     let allNamesMatchPattern = options.useConfigurationIf?.allNamesMatchPattern
     return (
       !allNamesMatchPattern ||
       nodeNames.every(nodeName => matches(nodeName, allNamesMatchPattern))
     )
   })
 }
rules/sort-classes.ts (1)

65-102: Minor: declare immutable defaults

Follow the same const pattern for consistency and safety.

-let defaultOptions: Required<SortClassesOptions[number]> = {
+const defaultOptions: Required<SortClassesOptions[number]> = {
utils/filter-options-by-declaration-comment-matches.ts (1)

35-37: Normalize JSDoc/block comment text before regex matching

Raw block comments include leading “*” and spacing; trimming alone can cause false negatives. Normalize comment text per line before matches().

Apply:

-    return parentComment.some(comment =>
-      matches(comment.value.trim(), declarationCommentMatchesPattern),
-    )
+    return parentComment.some(comment =>
+      matches(normalizeCommentValue(comment.value), declarationCommentMatchesPattern),
+    )

Add below in the file (outside this hunk):

function normalizeCommentValue(value: string): string {
  return value
    .split('\n')
    .map(line => line.replace(/^\s*\*?\s?/, '').trimEnd())
    .join('\n')
    .trim()
}
rules/sort-object-types/types.ts (1)

167-182: Remove vestigial 'multiline' selector mapping

AllowedModifiersPerSelector includes a 'multiline' key even though 'multiline' is not a Selector anymore. This is dead surface; deleting it tightens types.

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 cannot have modifiers. */
   'index-signature': never
 }
test/rules/sort-imports.test.ts (4)

2431-2438: Reset spies after tsconfig mocking

Add after: vi.resetAllMocks() to prevent cross-test leakage from readClosestTsConfigByPath mocks.

         before: () => {
           mockReadClosestTsConfigByPathWith({
             paths: {
               $path: ['./path'],
             },
           })
         },
+        after: () => {
+          vi.resetAllMocks()
+        },

6081-6088: Reset spies after tsconfig mocking (natural block)

Same leak risk here; reset mocks.

         before: () => {
           mockReadClosestTsConfigByPathWith({
             paths: {
               $path: ['./path'],
             },
           })
         },
+        after: () => {
+          vi.resetAllMocks()
+        },

9766-9773: Reset spies after tsconfig mocking (line-length block)

Mirror the reset to keep tests isolated.

         before: () => {
           mockReadClosestTsConfigByPathWith({
             paths: {
               $path: ['./path'],
             },
           })
         },
+        after: () => {
+          vi.resetAllMocks()
+        },

11263-11308: Optional: factor repeated customGroups into a helper

The long list is duplicated between valid/invalid cases; consider a small builder to cut noise.

const cg = (name: string) => (pattern: string) => ({ elementNamePattern: pattern, groupName: name })
rules/sort-heritage-clauses.ts (1)

150-175: Set partitionId per-partition (align with other rules).

Currently always 0; set it based on the current partition index.

-    let sortingNode: SortingNode = {
+    let sortingNodeBase: Omit<SortingNode, 'partitionId'> = {
       isEslintDisabled: isNodeEslintDisabled(
         heritageClause,
         eslintDisabledLines,
       ),
       size: rangeToDiff(heritageClause, sourceCode),
       node: heritageClause,
-      partitionId: 0,
       group,
       name,
     }
@@
-    formattedMembers.at(-1)!.push(sortingNode)
+    formattedMembers.at(-1)!.push({
+      ...sortingNodeBase,
+      partitionId: formattedMembers.length - 1,
+    })
rules/sort-imports.ts (2)

356-371: Provide newlinesBetweenValueGetter to actually report spacing errors.

Wire the getter and import getLinesBetween.

 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'
+import { getLinesBetween } from '../utils/get-lines-between'
@@
           reportAllErrors<MessageId>({
             availableMessageIds: {
               unexpectedDependencyOrder: 'unexpectedImportsDependencyOrder',
               missedSpacingBetweenMembers: 'missedSpacingBetweenImports',
               extraSpacingBetweenMembers: 'extraSpacingBetweenImports',
               unexpectedGroupOrder: 'unexpectedImportsGroupOrder',
               missedCommentAbove: 'missedCommentAboveImport',
               unexpectedOrder: 'unexpectedImportsOrder',
             },
             sortNodesExcludingEslintDisabled:
               createSortNodesExcludingEslintDisabled(sortingNodeGroups),
             sourceCode,
-            options,
+            options,
+            newlinesBetweenValueGetter: (left, right) =>
+              getLinesBetween(sourceCode, left, right),
             context,
             nodes,
           })

396-404: Guard against empty tsconfig.rootDir strings in schema.

Add minLength to avoid accidental '' which disables tsconfig resolution.

               rootDir: {
                 description: 'Specifies the tsConfig root directory.',
-                type: 'string',
+                type: 'string',
+                minLength: 1,
               },
rules/sort-decorators.ts (1)

269-283: Hook up newlinesBetweenValueGetter so spacing messages are emitted.

Add the getter and import getLinesBetween.

 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'
+import { getLinesBetween } from '../utils/get-lines-between'
@@
   reportAllErrors<MessageId>({
     availableMessageIds: {
       missedSpacingBetweenMembers: 'missedSpacingBetweenDecorators',
       extraSpacingBetweenMembers: 'extraSpacingBetweenDecorators',
       unexpectedGroupOrder: 'unexpectedDecoratorsGroupOrder',
       unexpectedOrder: 'unexpectedDecoratorsOrder',
     },
     ignoreFirstNodeHighestBlockComment: true,
     sortNodesExcludingEslintDisabled,
     sourceCode,
-    options,
+    options,
+    newlinesBetweenValueGetter: (left, right) =>
+      getLinesBetween(sourceCode, left, right),
     context,
     nodes,
   })
test/utils/filter-options-by-all-names-match.test.ts (1)

19-27: Add coverage for array patterns and anchored regex.

Optional: extend tests to ensure arrays and anchors behave as expected.

   it('returns options where all node names match `allNamesMatchPattern`', () => {
     let barContextOptions = buildContextOptions('bar')
     let contextOptions = [buildContextOptions('foo'), barContextOptions]
     let nodeNames = ['bar1', 'bar&foo']

     expect(filterOptionsByAllNamesMatch({ contextOptions, nodeNames })).toEqual(
       [barContextOptions],
     )
   })
+
+  it('supports array patterns and anchored regex', () => {
+    let contextOptions = [
+      buildContextOptions(['^lib-', '^core-']),
+      buildContextOptions(['^app-']),
+    ]
+    let nodeNames = ['lib-utils', 'core-types']
+    expect(
+      filterOptionsByAllNamesMatch({ contextOptions, nodeNames }),
+    ).toEqual([contextOptions[0]])
+  })
test/utils/filter-options-by-declaration-comment-matches.test.ts (2)

4-4: Avoid coupling tests to AST_TOKEN_TYPES for comments; use literal 'Line' to match TSESTree.Comment.

AST_TOKEN_TYPES may drift; TSESLint expects comments with type 'Line' | 'Block'. Use string literals and drop the import.

-import { AST_TOKEN_TYPES } from '@typescript-eslint/utils'
+// (no import needed)
   return {
     getCommentsBefore: () =>
       comments.map(comment => ({
-        loc: null as unknown as TSESTree.SourceLocation,
-        type: AST_TOKEN_TYPES.Line,
+        loc: null as unknown as TSESTree.SourceLocation,
+        type: 'Line',
         value: comment,
         range: [0, 0],
       })),
   } as unknown as TSESLint.SourceCode

Also applies to: 71-80


40-55: Nice positive match case; consider adding array/regex forms.

Add a case for ['foo', { pattern: 'bar', flags: 'i' }] to exercise all RegexOption shapes.

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

302-317: Conflicting guidance: points to declarationMatchesPattern, which isn’t listed for this rule.

Either (a) add declarationMatchesPattern to useConfigurationIf for sort-objects, or (b) change this deprecation note to reference declarationCommentMatchesPattern/callingFunctionNamePattern + type: 'unsorted'.

-Use the [useConfigurationIf.declarationMatchesPattern](#useconfigurationif) option alongside [type: unsorted](#type) instead.
+Use [useConfigurationIf.declarationCommentMatchesPattern](#useconfigurationif) (and/or `callingFunctionNamePattern`) alongside [type: 'unsorted'] instead.
docs/content/rules/sort-object-types.mdx (1)

339-349: *Invalid regex example (‘Metadata$’).

Leading '*' is not a valid JS regex. Use '.*Metadata$' (or '^.*Metadata$') to avoid user confusion.

-        declarationMatchesPattern: '*Metadata$',
+        declarationMatchesPattern: '.*Metadata$',
test/rules/sort-object-types.test.ts (1)

338-370: Tests use a property literally named “member”, which reads like a group name.

This can be misread in failure diffs (leftGroup: 'member', left: 'member'). Consider renaming the property to something neutral (e.g., propX) to reduce ambiguity while preserving the scenario.

Also applies to: 372-404, 2906-2937, 2940-2971, 5424-5456, 5458-5490

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

373-383: *Invalid regex example (‘Metadata$’).

Use '.*Metadata$' to show a valid pattern.

-        declarationMatchesPattern: '*Metadata$',
+        declarationMatchesPattern: '.*Metadata$',
rules/sort-object-types/get-custom-groups-compare-options.ts (1)

51-55: Minor readability: avoid destructuring assignment with a leading semicolon.

Use a direct assignment to reduce cognitive overhead.

-    if ('sortBy' in customGroup && customGroup.sortBy) {
-      ;({ sortBy } = customGroup)
-    }
+    if ('sortBy' in customGroup && customGroup.sortBy) {
+      sortBy = customGroup.sortBy
+    }
test/rules/sort-interfaces.test.ts (2)

2443-2496: declarationCommentMatchesPattern: solid coverage.

Line-comment gating is exercised with both valid and invalid cases. Consider adding one block-comment case to mirror object rules’ tests for symmetry.


360-411: Same-line comments and semicolons: consistent after-fix outputs.

A few outputs mix 'something' and "something" across suites; not harmful but consider unifying quotes to reduce churn in snapshots.

Also applies to: 3019-3043, 5580-5604

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

168-183: Tighten AllowedModifiersPerSelector for regular objects.

multiline and index-signature aren’t valid selectors for this rule; keeping them here is confusing. Consider removing these keys.

 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
 }
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3d58205 and 979f8b3.

📒 Files selected for processing (35)
  • docs/content/rules/sort-interfaces.mdx (3 hunks)
  • docs/content/rules/sort-object-types.mdx (3 hunks)
  • docs/content/rules/sort-objects.mdx (5 hunks)
  • rules/sort-array-includes.ts (5 hunks)
  • rules/sort-classes.ts (1 hunks)
  • rules/sort-decorators.ts (6 hunks)
  • rules/sort-enums.ts (5 hunks)
  • rules/sort-exports.ts (2 hunks)
  • rules/sort-heritage-clauses.ts (6 hunks)
  • rules/sort-imports.ts (6 hunks)
  • rules/sort-interfaces.ts (2 hunks)
  • rules/sort-intersection-types.ts (1 hunks)
  • rules/sort-jsx-props.ts (7 hunks)
  • rules/sort-maps.ts (3 hunks)
  • rules/sort-modules.ts (2 hunks)
  • rules/sort-named-exports.ts (2 hunks)
  • rules/sort-named-imports.ts (2 hunks)
  • rules/sort-object-types.ts (10 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 (10 hunks)
  • rules/sort-objects/types.ts (5 hunks)
  • rules/sort-switch-case.ts (1 hunks)
  • rules/sort-union-types.ts (1 hunks)
  • rules/sort-variable-declarations.ts (1 hunks)
  • test/rules/sort-imports.test.ts (25 hunks)
  • test/rules/sort-interfaces.test.ts (18 hunks)
  • test/rules/sort-object-types.test.ts (19 hunks)
  • test/rules/sort-object-types/get-custom-groups-compare-options.test.ts (1 hunks)
  • test/rules/sort-objects.test.ts (31 hunks)
  • test/utils/filter-options-by-all-names-match.test.ts (1 hunks)
  • test/utils/filter-options-by-declaration-comment-matches.test.ts (1 hunks)
  • test/utils/get-matching-context-options.test.ts (0 hunks)
  • utils/filter-options-by-all-names-match.ts (3 hunks)
  • utils/filter-options-by-declaration-comment-matches.ts (1 hunks)
💤 Files with no reviewable changes (1)
  • test/utils/get-matching-context-options.test.ts
🚧 Files skipped from review as they are similar to previous changes (4)
  • test/rules/sort-object-types/get-custom-groups-compare-options.test.ts
  • rules/sort-named-exports.ts
  • rules/sort-named-imports.ts
  • rules/sort-enums.ts
🧰 Additional context used
🧬 Code graph analysis (24)
utils/filter-options-by-declaration-comment-matches.ts (4)
rules/sort-object-types/types.ts (1)
  • Options (28-112)
rules/sort-objects/types.ts (1)
  • Options (25-120)
types/common-options.ts (1)
  • RegexOption (477-477)
utils/matches.ts (1)
  • matches (39-60)
utils/filter-options-by-all-names-match.ts (3)
rules/sort-interfaces.ts (1)
  • Options (12-12)
rules/sort-object-types/types.ts (1)
  • Options (28-112)
rules/sort-objects/types.ts (1)
  • Options (25-120)
test/utils/filter-options-by-declaration-comment-matches.test.ts (2)
utils/filter-options-by-declaration-comment-matches.ts (1)
  • filterOptionsByDeclarationCommentMatches (14-39)
types/common-options.ts (1)
  • RegexOption (477-477)
rules/sort-switch-case.ts (2)
rules/sort-array-includes.ts (1)
  • defaultOptions (60-74)
rules/sort-object-types/types.ts (1)
  • Options (28-112)
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)
test/utils/filter-options-by-all-names-match.test.ts (2)
utils/filter-options-by-all-names-match.ts (1)
  • filterOptionsByAllNamesMatch (80-94)
types/common-options.ts (1)
  • RegexOption (477-477)
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-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-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-classes.ts (2)
rules/sort-array-includes.ts (1)
  • defaultOptions (60-74)
rules/sort-classes/types.ts (1)
  • SortClassesOptions (25-66)
rules/sort-modules.ts (2)
rules/sort-array-includes.ts (1)
  • defaultOptions (60-74)
rules/sort-modules/types.ts (1)
  • SortModulesOptions (25-59)
rules/sort-array-includes.ts (6)
types/sorting-node.ts (1)
  • SortingNode (18-102)
rules/sort-array-includes/types.ts (1)
  • Options (24-68)
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)
test/rules/sort-imports.test.ts (1)
rules/sort-imports/types.ts (1)
  • Options (29-141)
rules/sort-objects/types.ts (1)
types/common-options.ts (2)
  • RegexOption (477-477)
  • CustomGroupsOption (103-140)
rules/sort-heritage-clauses.ts (11)
rules/sort-heritage-clauses/types.ts (1)
  • Options (14-22)
utils/common-json-schemas.ts (5)
  • buildCustomGroupsArrayJsonSchema (302-351)
  • partitionByNewLineJsonSchema (268-272)
  • partitionByCommentJsonSchema (241-262)
  • 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 (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-exports.ts (5)
types/sorting-node.ts (1)
  • SortingNode (18-102)
rules/sort-array-includes.ts (1)
  • defaultOptions (60-74)
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/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-imports.ts (8)
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)
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-decorators.ts (6)
rules/sort-decorators/types.ts (1)
  • Options (16-29)
utils/common-json-schemas.ts (3)
  • buildCustomGroupsArrayJsonSchema (302-351)
  • partitionByNewLineJsonSchema (268-272)
  • 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)
utils/does-custom-group-match.ts (1)
  • doesCustomGroupMatch (121-141)
utils/get-custom-groups-compare-options.ts (1)
  • buildGetCustomGroupOverriddenOptionsFunction (137-148)
rules/sort-interfaces.ts (2)
rules/sort-array-includes.ts (1)
  • defaultOptions (60-74)
rules/sort-object-types/types.ts (1)
  • Options (28-112)
rules/sort-jsx-props.ts (5)
rules/sort-array-includes.ts (1)
  • defaultOptions (60-74)
rules/sort-jsx-props/types.ts (1)
  • Options (24-71)
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-objects.ts (6)
rules/sort-objects/types.ts (1)
  • Options (25-120)
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)
rules/sort-object-types.ts (5)
rules/sort-array-includes.ts (1)
  • defaultOptions (60-74)
rules/sort-object-types/types.ts (1)
  • Options (28-112)
utils/matches.ts (1)
  • matches (39-60)
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-object-types/get-custom-groups-compare-options.ts (1)
rules/sort-object-types/types.ts (1)
  • Options (28-112)
🪛 ESLint
test/rules/sort-object-types.test.ts

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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)

test/rules/sort-interfaces.test.ts

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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


[error] 599-599: 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] 2399-2399: Unsafe use of a(n) error type typed template tag.

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)

test/rules/sort-imports.test.ts

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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)

test/rules/sort-objects.test.ts

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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)

🔇 Additional comments (42)
rules/sort-intersection-types.ts (1)

20-20: Approve — Required<Options[number]> is correct; verify no leftover Options[0]

Switching to Required<Options[number]> avoids tuple-index narrowing and aligns with the shared Options[] typing.

Automated search produced no output; run locally to confirm no occurrences remain:

rg -nP --type=ts '\bOptions\[\s*0\s*\]' -C2
rg -nP --type=ts '\bRequired<\s*Options\[\s*0\s*\]\s*>' -C2
rules/sort-switch-case.ts (1)

30-38: Type tweak to Options[number] is correct and aligns with repo-wide pattern

Using Required<Options[number]> future‑proofs the defaultOptions typing for tuple/array Options. No behavior change.

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

50-63: Consistent shift to Options[number]

Matches the new options-array convention; default object keys look compatible with the rule’s Options.

rules/sort-variable-declarations.ts (1)

50-63: Options[number] typing LGTM

Brings this rule in line with others; no runtime impact.

rules/sort-classes.ts (1)

65-102: Adopting SortClassesOptions[number] is appropriate

Type-only change; default keys align with the rule types and usage.

utils/filter-options-by-all-names-match.ts (1)

49-49: Docs updated to new API name — verify no stale imports remain

Examples now call filterOptionsByAllNamesMatch; ensure every import/usage of the old getMatchingContextOptions is replaced across the repo.
Check: utils/filter-options-by-all-names-match.ts (lines 49, 62).
Re-run verification from repo root: rg -n --hidden --no-ignore-vcs -S '\bgetMatchingContextOptions\b' -g '!dist/**' -C3 || git grep -n 'getMatchingContextOptions'

rules/sort-modules.ts (2)

66-66: Type widening to Options[number] looks good

Matches the project-wide typing pattern for defaultOptions. No behavioral changes.


171-171: Consistent parameter typing

Using Required<SortModulesOptions[number]> for analyzeModule keeps types aligned with completed options.

rules/sort-array-includes.ts (3)

32-32: Switch to filterOptionsByAllNamesMatch is appropriate

Correctly scopes options based on element names; aligns with the new matching utilities.


56-58: Type alias simplification is fine

Using SortingNode<TSESTree.SpreadElement | TSESTree.Expression> removes the unused groupKind surface.


60-74: Default groups contain only 'literal' — spreads become “unknown”

With groups: ['literal'], SpreadElements fall into the unknown bucket and will be sorted unless explicitly ignored. If the intent is to leave spreads untouched by default, treat unknown groups as ignored during sorting (see next comment).

Do we want spreads sorted by default? If not, apply the next change.

rules/sort-exports.ts (4)

50-52: Type alias clean-up is solid

Removing groupKind from the node type aligns with the groups-based architecture.


54-67: Default options with empty groups preserve mixed sorting

Empty groups mean all nodes share the same group; the rule still sorts consistently by name. Looks good.


151-162: Groups-based sorting flow LGTM

Using sortNodesByGroups with per-group overrides is consistent with other rules. No need to ignore unknowns here since groups are empty by default.


165-179: Error reporting wiring is correct

Message IDs map correctly; flattened nodes passed into reportAllErrors match expected contract.

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

35-40: New declarationCommentMatchesPattern hook looks correct

Matches the new conditional-config pattern used elsewhere; documentation is clear.


58-64: Per-custom-group fallbackSort extension is a nice addition

Allows finer control without widening global options.

test/rules/sort-imports.test.ts (5)

1462-1475: LGTM: good coverage for per-group newlinesBetween overriding global

Accurately exercises precedence with a sentinel unusedGroup.


1534-1551: LGTM: “never” fences between groups regardless of global setting

Solid assertions on spacing normalization.


1613-1626: LGTM: ignore/never/0 interaction preserved

Scenarios look correct and future‑proof for spacing behavior.


7908-7917: LGTM: targeted customGroups with modifiers

Nice demonstration of value‑only selector via modifiers: ['value'].


11559-11570: LGTM: precise typing for groups in helper

Options[number]['groups'] keeps the tests aligned with the exported type.

test/utils/filter-options-by-declaration-comment-matches.test.ts (1)

11-25: Good coverage for “undefined/empty” behavior.

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

414-432: Great addition of declarationCommentMatchesPattern examples.

docs/content/rules/sort-object-types.mdx (1)

351-369: Nice, clear example for declarationCommentMatchesPattern.

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

2370-2425: Solid coverage for declarationCommentMatchesPattern in rule tests.


2210-2238: Good move to two-option arrays for allNamesMatchPattern scenarios.

This mirrors runtime matching precedence and prevents false positives.

Also applies to: 4778-4806, 7290-7317

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

385-403: Clear, practical example for declarationCommentMatchesPattern.

rules/sort-object-types/get-custom-groups-compare-options.ts (1)

8-11: API shape update looks good and matches Options[number] usage across the repo.

Also applies to: 31-37

rules/sort-maps.ts (1)

81-89: No action required — complete() safely handles undefined; filterOptionsByAllNamesMatch may return []

filterOptionsByAllNamesMatch can return [] when no context option matches (tests cover this), and complete(matchedContextOptions[0], settings, defaultOptions) uses a default parameter ({}), so passing undefined is safe.

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

552-584: Group name “member”: scenarios covered; looks good.

The new “member” predefined group is exercised across alphabetical/natural/line‑length. Assertions and options arrays align with the new grouping surface.

Please confirm docs list “member” in the predefined groups for sort-interfaces so users can discover it.

Also applies to: 3184-3216, 5745-5777


586-618: Method over member precedence: consistent across modes.

Test cases clearly assert method > member ordering with matching fixes. No action needed.

Also applies to: 3219-3250, 5779-5811


2321-2349: Multi-configuration selection with allNamesMatchPattern is correct.

Two-option arrays demonstrate precedence fallback and targeted activation (foo vs RGB). Good coverage.

Also applies to: 4961-4980, 7507-7534


2389-2440: declarationMatchesPattern flow validated.

Tests cover enable-on-name then fallback to default options. Good.

Also applies to: 5021-5072, 7575-7626


1398-1417: Partition-by-newline behavior: nice set of positive/negative tests.

Readability looks good; fixes preserve blank lines between partitions.

Also applies to: 4029-4050, 6588-6611


1869-1887: Whitespace normalization tests: helpful.

These catch spacing fixups alongside ordering. No issues.

Also applies to: 4501-4519, 7055-7072


452-516: Complex predefined groups: expectations updated to new group names.

The switch to optional‑multiline‑member etc. is reflected correctly.

Also applies to: 3084-3147, 5646-5709

rules/sort-objects.ts (5)

66-85: Defaults updated to array-based Options and empty customGroups: good.

Typings and defaults (Required<Options[number]>, customGroups: [], groups: []) look consistent with the new schema.

Ensure docs for sort-objects reflect: top-level customGroups array, declarationCommentMatchesPattern, and destructuredObjects.groups flag.


426-453: JSON schema: top-level customGroups and declarationCommentMatchesPattern wired correctly.

Schema changes align with the new API surface.


99-106: Context option matching pipeline is clear and ordered.

Filtering by names, then declaration comment, then calling function is sensible and predictable.

Also applies to: 111-121


241-345: Formatting pipeline and modifiers/selectors classification looks solid.

Method/property detection, multiline modifier, predefined groups caching, and computeGroup usage are correct.


146-150: ESLint-disable awareness preserved via sortNodesExcludingEslintDisabled.

Good separation of sorting with ignore toggles and centralized reporting.

Also applies to: 381-395

Comment on lines +1 to +2
import type { TSESLint } from '@typescript-eslint/utils'

Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Enable spacing diagnostics (missed/extra blank lines).

Pass newlinesBetweenValueGetter so reportAllErrors can evaluate newlinesBetween 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,
         })

Also applies to: 198-212

🤖 Prompt for AI Agents
In rules/sort-jsx-props.ts around lines 1-2 and also apply the same change at
198-212, enable spacing diagnostics for missed/extra blank lines by passing the
newlinesBetweenValueGetter into the reportAllErrors call (so reportAllErrors can
evaluate the newlinesBetween option for JSX props); add or import a
newlinesBetweenValueGetter function if missing and thread it through to where
reportAllErrors is invoked, ensuring the call signature includes this getter and
that reportAllErrors uses it when computing spacing/newline diagnostics.

Comment on lines +571 to +592
if (callParent) {
return {
name: sourceCode.getText(callParent.callee),
type: 'CallExpression',
node: callParent,
}
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Normalize callingFunctionNamePattern callee text to reduce false positives.

Using sourceCode.getText(callParent.callee) can include arbitrary expressions (e.g., (0, foo.bar)). Consider extracting a dotted identifier when possible to make matching predictable.

Example:

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 fall back to getText only when null.

🤖 Prompt for AI Agents
In rules/sort-objects.ts around lines 571 to 577, the code uses
sourceCode.getText(callParent.callee) which can return arbitrary wrapped
expressions and cause false positives; change this to first normalize the callee
by extracting a stable name: if callee.type is Identifier return its name; if
MemberExpression and not computed and property is Identifier return the property
name or a dotted "object.property" string as desired; only if those checks fail,
fall back to sourceCode.getText(callParent.callee); then use that normalized
string in the returned object so callingFunctionNamePattern matching is
predictable.

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 (17)
test/rules/sort-sets.test.ts (2)

978-985: Fix quoted spread literals ('...foo'): they should be spreads, not strings.

These cases currently test a string literal instead of a SpreadElement, weakening coverage of the spread selector.

Apply per block (3 occurrences):

-            '...foo',
+            ...foo,

and

-            '...foo',
+            ...foo,

Also applies to: 985-991, 2500-2506, 2507-2513, 4022-4028, 4029-4035


4597-4603: Invalid Set constructor in “custom → sorts elements in sets”.

new Set('a','b',...) is not valid usage; pass an iterable.

Apply:

-          new Set(
-            'a',
-            'b',
-            'c',
-            'd',
-          )
+          new Set([
+            'a',
+            'b',
+            'c',
+            'd',
+          ])
rules/sort-object-types/types.ts (2)

225-233: Fix group type construction (avoids impossible 'optional-required-*' and removes modifiers from index-signature).

Current JoinWithDash over literal tokens produces a single impossible key (e.g., 'optional-required-multiline-property'), and index signatures are documented as having no modifiers. Define groups via template unions and keep index-signature bare.

- type IndexSignatureGroup = JoinWithDash<
-   [
-     OptionalModifier,
-     RequiredModifier,
-     MultilineModifier,
-     IndexSignatureSelector,
-   ]
- >
+ // Index signatures cannot have modifiers.
+ type IndexSignatureGroup = 'index-signature'
 
- type PropertyGroup = JoinWithDash<
-   [OptionalModifier, RequiredModifier, MultilineModifier, PropertySelector]
- >
+ // Compose allowed modifier prefixes without impossible combos.
+ type ModifierPrefix<S extends string> =
+   | S
+   | `optional-${S}`
+   | `required-${S}`
+   | `multiline-${S}`
+   | `optional-multiline-${S}`
+   | `required-multiline-${S}`
+
+ type PropertyGroup = ModifierPrefix<'property'>
 
- type MemberGroup = JoinWithDash<
-   [OptionalModifier, RequiredModifier, MultilineModifier, MemberSelector]
- >
+ type MemberGroup = ModifierPrefix<'member'>
 
- type MethodGroup = JoinWithDash<
-   [OptionalModifier, RequiredModifier, MultilineModifier, MethodSelector]
- >
+ type MethodGroup = ModifierPrefix<'method'>

Also applies to: 241-243, 267-269, 278-281


96-101: Remove deprecated ignorePattern across the codebase or keep & document (mandatory refactor required).

ignorePattern is still referenced in runtime logic, defaults, types, schemas, tests, and docs — deleting the type alone will break the repo. Update all usages or keep and document a migration path.

  • Key locations that must be changed:
    • rules/sort-object-types.ts (default + schema + runtime check using options.ignorePattern — e.g. runtime check around line ~194)
    • rules/sort-object-types/types.ts (ignorePattern: RegexOption)
    • rules/sort-objects.ts / rules/sort-objects/types.ts (defaults, runtime matches(..., options.ignorePattern), schema)
    • rules/sort-jsx-props.ts / rules/sort-jsx-props/types.ts (defaults, runtime use of options.ignorePattern, schema)
    • rules/sort-interfaces.ts / rules/sort-interfaces/types.ts
    • utils/get-settings.ts (declaration and settings list include ignorePattern)
    • tests: test/rules/*.test.ts (many tests pass/expect ignorePattern) and test/utils/get-settings.test.ts
    • docs: docs/content/rules/*.mdx and docs/content/guide/getting-started.mdx (DEPRECATED sections and examples)
  • Actions:
    • If dropping in v5: remove ignorePattern declarations and defaults, remove schema entries, refactor runtime checks to the appropriate useConfigurationIf.* replacement (e.g., declarationMatchesPattern / tagMatchesPattern where applicable), update utils/get-settings, update tests and docs, add migration notes/changelog entry, run full test suite.
    • If keeping until v5: keep code paths and types, mark rule-level support explicitly, add a clear removal timeline in docs/migrations, and update tests/docs to reflect the timeline.
test/rules/sort-array-includes.test.ts (3)

1183-1196: Fix: use spread element, not a string literal, in anyOf test

'...foo' should be a spread element (...foo). The current quotes make it a literal and fail to exercise selector: 'spread'.

-            '...foo',
+            ...foo,

2979-2993: Fix: use spread element, not a string literal, in anyOf test (natural section)

Same issue in the natural sorting block.

-            '...foo',
+            ...foo,

4756-4768: Fix: use spread element, not a string literal, in anyOf test (line-length section)

Same issue in the line-length sorting block.

-            '...foo',
+            ...foo,
docs/content/rules/sort-array-includes.mdx (1)

250-258: Docs/API mismatch: newlinesBetween supports 'always' and 'never'

Schema and tests allow 'always'|'never' in addition to numbers/'ignore'. Update docs.

-<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.
+- `'never'` — No newlines are allowed (equivalent to `0`).
+- `'always'` — Enforce at least one newline (use a number for an exact count).
+- `0` — No newlines are allowed.
+- Any other number — Enforce this exact number of newlines between each group, and forbid newlines inside groups.
docs/content/rules/sort-objects.mdx (1)

575-578: customGroups type still shows deprecated object shape

This section still documents { [groupName: string]: string | string[] } although the page migrates to the array API. Update to the new array type to prevent user confusion.

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

221-233: Fix incorrect type for [DEPRECATED] ignorePattern

The type block shows a wrapped object with allNamesMatchPattern, which is unrelated to ignorePattern. Suggest using the direct pattern types.

Apply this diff:

-### [DEPRECATED] ignorePattern
-
-<sub>
-  type:
-  ```
-  {
-    allNamesMatchPattern?: string | string[] | { pattern: string; flags: string } | { pattern: string; flags: string }[]
-  }
-  ```
-</sub>
+### [DEPRECATED] ignorePattern
+
+<sub>
+  type:
+  ```
+  string | string[] | { pattern: string; flags?: string } | { pattern: string; flags?: string }[]
+  ```
+</sub>
 <sub>default: `[]`</sub>
test/rules/sort-object-types.test.ts (1)

252-276: Use optional-multiline-member consistently (docs + schema check required)

Tests already use the new identifier (test/rules/sort-object-types.test.ts, test/rules/sort-interfaces.test.ts); documentation still contains the old form multiline-optional-member (examples in docs/content/rules/sort-object-types.mdx and docs/content/rules/sort-interfaces.mdx). Replace stale multiline-optional-member occurrences with optional-multiline-member and verify the groups JSON/schema/generator (rules/sort-object-types/types.ts, utils/generate-predefined-groups*, utils/common-json-schemas*) accept the new identifier.

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

1-6: Change SortNamedImportsSortingNode to SortingNode<TSESTree.ImportSpecifier>

rules/sort-named-imports/types.ts currently declares SortNamedImportsSortingNode = SortingNode<TSESTree.ImportClause> (line 95) but the rule builds sorting nodes from ImportSpecifier nodes (e.g., checks specifier.type === 'ImportSpecifier' and uses the specifier as the node). Update the type to SortingNode<TSESTree.ImportSpecifier>.

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

7966-7979: Remove deprecated ignorePattern in v5; switch to useConfigurationIf.

v5 scope removes ignorePattern. Update this test to the new conditional-config to keep parity.

-        options: [
-          {
-            ignorePattern: ['Ignore'],
-            type: 'line-length',
-            order: 'desc',
-          },
-        ],
+        options: [
+          {
+            useConfigurationIf: { declarationMatchesPattern: 'Ignore' },
+            // prevent sorting when the declaration matches
+            type: 'unsorted',
+          },
+        ],
docs/content/rules/sort-heritage-clauses.mdx (1)

376-403: Drop legacy ESLint v8 config example or mark unsupported in v5 ESM-only.

Since v5 drops ESLint v8 and is ESM-only, the .eslintrc.js example is misleading. Recommend removal.

-    {
-      source: dedent`
-        // .eslintrc.js
-        module.exports = {
-          plugins: [
-            'perfectionist',
-          ],
-          rules: {
-            'perfectionist/sort-heritage-clauses': [
-              'error',
-              {
-                type: 'alphabetical',
-                order: 'asc',
-                fallbackSort: { type: 'unsorted' },
-                ignoreCase: true,
-                specialCharacters: 'keep',
-                partitionByComment: false,
-                partitionByNewLine: false,
-                newlinesBetween: 'ignore',
-                groups: [],
-                customGroups: [],
-              },
-            ],
-          },
-        }
-      `,
-      name: 'Legacy Config',
-      value: 'legacy',
-    },
rules/sort-jsx-props/types.ts (1)

65-70: Remove deprecated ignorePattern in v5.

The v5 plan removes ignorePattern across rules. Drop it from the public Options type.

-    /**
-     * @deprecated Since v4.11.0. Will be removed in v5.0.0. Use
-     *   {@link `useConfigurationIf.tagMatchesPattern`} instead.
-     */
-    ignorePattern: RegexOption
utils/make-newlines-between-fixes.ts (2)

165-171: Fix EOL handling (CRLF gets split, yielding “\r\n\n” artifacts).

The helpers assume LF only and use indexOf('\n'), which splits CRLF pairs and can produce mixed line endings on Windows. Preserve the file’s native EOL detected from sourceCode.text and use it consistently for insertions and normalization.

Apply this diff:

@@
-    let rangeReplacement = computeRangeReplacement({
+    // Preserve file EOL style (LF vs CRLF)
+    let eol: '\n' | '\r\n' = sourceCode.text.includes('\r\n') ? '\r\n' : '\n'
+
+    let rangeReplacement = computeRangeReplacement({
       isOnSameLine:
         sortingNode.node.loc.end.line === nextSortingNode.node.loc.start.line,
       textBetweenNodes,
       newlinesBetween,
+      eol,
     })
@@
-function computeRangeReplacement({
-  textBetweenNodes,
-  newlinesBetween,
-  isOnSameLine,
-}: {
-  textBetweenNodes: string
-  newlinesBetween: number
-  isOnSameLine: boolean
-}): undefined | string {
-  let textBetweenNodesWithoutInvalidNewlines =
-    getStringWithoutInvalidNewlines(textBetweenNodes)
+function computeRangeReplacement({
+  textBetweenNodes,
+  newlinesBetween,
+  isOnSameLine,
+  eol,
+}: {
+  textBetweenNodes: string
+  newlinesBetween: number
+  isOnSameLine: boolean
+  eol: '\n' | '\r\n'
+}): undefined | string {
+  let textBetweenNodesWithoutInvalidNewlines =
+    getStringWithoutInvalidNewlines(textBetweenNodes, eol)
@@
-    rangeReplacement = addNewlineBeforeFirstNewline(rangeReplacement)
+    rangeReplacement = addNewlineBeforeFirstNewline(rangeReplacement, eol)
   }
   if (!isOnSameLine) {
     return rangeReplacement
   }
-  return addNewlineBeforeFirstNewline(rangeReplacement)
+  return addNewlineBeforeFirstNewline(rangeReplacement, eol)
 }
@@
-function addNewlineBeforeFirstNewline(value: string): string {
-  let firstNewlineIndex = value.indexOf('\n')
+function addNewlineBeforeFirstNewline(value: string, eol: '\n' | '\r\n'): string {
+  let firstNewlineIndex = value.indexOf(eol)
   if (firstNewlineIndex === -1) {
-    return `${value}\n`
+    return `${value}${eol}`
   }
-  return `${value.slice(0, firstNewlineIndex)}\n${value.slice(firstNewlineIndex)}`
+  return `${value.slice(0, firstNewlineIndex)}${eol}${value.slice(firstNewlineIndex)}`
 }
@@
-function getStringWithoutInvalidNewlines(value: string): string {
-  return value.replaceAll(/\n\s*\n/gu, '\n').replaceAll(/\n+/gu, '\n')
+function getStringWithoutInvalidNewlines(value: string, eol: '\n' | '\r\n'): string {
+  // Collapse whitespace-only blank lines and multiple consecutive line breaks.
+  return value
+    .replace(/\r?\n[ \t]*\r?\n/gu, eol)
+    .replace(/(?:\r?\n){2,}/gu, eol)
 }

Also applies to: 232-238, 249-251


103-121: Map sortedNodes -> original indices before using nodes[i]; current indexing can produce wrong ranges

sortedNodes is the post‑sort ordering while nodes is the original order. The loop indexes both with i (computes semantics from sortedNodes but reads ranges from nodes.at(i)/nodes.at(i+1)), so when reordering occurs the pair used to compute newlines may not match the pair whose range is replaced.

  • File: utils/make-newlines-between-fixes.ts (around lines 103–121) — stop using nodes.at(i)/nodes.at(i+1) directly.
  • Fix: build an index map (use utils/create-node-index-map.ts), then for each sorted pair do:
    • leftIdx = nodeIndexMap.get(sortedSortingNode)!, rightIdx = nodeIndexMap.get(nextSortedSortingNode)!
    • derive sortingNode = nodes[Math.min(leftIdx, rightIdx)] and nextSortingNode = nodes[Math.max(leftIdx, rightIdx)]
    • use those for getNodeRange/getLinesBetween and replacement.
  • Add dev-only asserts (e.g., sortedNodes.length === nodes.length and nodeIndexMap.has(...)) and tests that cover reordered pairs.
♻️ Duplicate comments (19)
vite.config.ts (2)

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

This config will crash on Node 20. Replace import.meta.dirname with an ESM-safe __dirname shim.

Apply within this 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'),

Add near the imports (top of file):

import { fileURLToPath } from 'node:url'
const __dirname = path.dirname(fileURLToPath(import.meta.url))

29-32: Same issue in dts include — switch to __dirname

Use the same ESM-safe __dirname here to keep Node 20 support.

-        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'),
rules/sort-array-includes.ts (1)

60-74: Default groups: ['literal'] changes behavior for spreads. Verify intent.

With this default, spreads get sorted under the “unknown” bucket. If the intention is to keep unlisted selectors (like spreads) stable by default, ignore them during sorting.

Apply:

   function sortNodesExcludingEslintDisabled(
     ignoreEslintDisabledNodes: boolean,
   ): SortArrayIncludesSortingNode[] {
     return formattedMembers.flatMap(nodes =>
       sortNodesByGroups({
         getOptionsByGroupIndex:
           buildGetCustomGroupOverriddenOptionsFunction(options),
         ignoreEslintDisabledNodes,
+        isNodeIgnored: node =>
+          getGroupIndex(options.groups, node) === options.groups.length,
         groups: options.groups,
         nodes,
       }),
     )
   }

Note: ensure getGroupIndex is imported from the shared groups utility used elsewhere in the codebase.

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

4-4: Replace untyped dedent with typed variant to silence typescript/no-unsafe-call.

Use ts-dedent (or cast once) to avoid unsafe tagged template calls in tests.

-import dedent from 'dedent'
+import dedent from 'ts-dedent'

3156-3161: Same remarks as earlier blocks.

These mirrored changes/tests repeat the patterns already reviewed above (array-based customGroups, group precedence, and newline controls). No additional issues spotted.

Also applies to: 4482-4511, 4565-4567, 4637-4657, 5923-5955, 7296-7325, 7380-7380, 7451-7472, 8543-8550

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

192-205: Blocker: missing newlinesBetweenValueGetter breaks spacing diagnostics

reportAllErrors requires newlinesBetweenValueGetter to report missed/extra spacing. Tests rely on missedSpacingBetweenHeritageClauses/extraSpacingBetweenHeritageClauses. Add the getter.

 import { reportAllErrors } from '../utils/report-all-errors'
 import { shouldPartition } from '../utils/should-partition'
+import { getLinesBetween } from '../utils/get-lines-between'
@@
     reportAllErrors<MessageId>({
       availableMessageIds: {
         missedSpacingBetweenMembers: 'missedSpacingBetweenHeritageClauses',
         extraSpacingBetweenMembers: 'extraSpacingBetweenHeritageClauses',
         unexpectedGroupOrder: 'unexpectedHeritageClausesGroupOrder',
         unexpectedOrder: 'unexpectedHeritageClausesOrder',
       },
       sortNodesExcludingEslintDisabled:
         createSortNodesExcludingEslintDisabled(nodes),
+      newlinesBetweenValueGetter: (left, right) =>
+        getLinesBetween(sourceCode, left, right),
       sourceCode,
       options,
       context,
       nodes,
     })
rules/sort-jsx-props.ts (1)

198-212: Enable spacing diagnostics (missed/extra blank lines)

Pass newlinesBetweenValueGetter so reportAllErrors can enforce newlinesBetween for JSX props.

+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,
         })
docs/content/rules/sort-heritage-clauses.mdx (5)

148-159: Fix terminology (decorators → heritage clauses) and make RegExpPattern.flags optional.

Apply to keep consistent with types and other rule docs.

 ### partitionByComment

 <sub>default: `false`</sub>

-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.
+- `{ block: boolean | RegExpPattern | RegExpPattern[]; line: boolean | RegExpPattern | RegExpPattern[] }` — Specify which block and line comments should act as delimiters.

168-176: Document full newlinesBetween union and semantics.

-<sub>type: `number | 'ignore'`</sub>
+<sub>type: `'ignore' | 'always' | 'never' | number`</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 (equivalent to `0`).
+- `number` — Require exactly this number of blank lines between groups.

265-273: Unify CustomGroupDefinition typing (add 'custom'; proper fallbackSort; newlinesInside union).

 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: Mirror typing fixes in CustomGroupAnyOfDefinition and keep selector documented in anyOf.

 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-303: Document the selector attribute in Attributes.

 #### 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-jsx-props/types.ts (2)

106-111: Selector JSDoc is stale; only 'prop' is allowed.

Update to avoid misconfiguration.

-  /**
-   * 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') for specificity.
+   */

119-124: Align Selector JSDoc with narrowed type.

-/**
- * 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 via modifiers.
+ */
test/rules/sort-imports.test.ts (1)

4310-4379: Fix ESLint no-unsafe-call for dedent (same issue as before).

Add a one-line local disable before each newly added tagged dedent call here to silence @typescript-eslint/no-unsafe-call (or switch to ts-dedent later). Mirrors the earlier review around these lines.

@@
-      await valid({
-        code: dedent`
+      await valid({
+        // 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`
test/rules/sort-jsx-props.test.ts (2)

259-260: Consistent migration to 'multiline-prop'.

Group ordering and error data reflect the new identifier; assertions read well.

Also applies to: 284-285


868-875: Custom group descriptors: coverage is solid.

Multiple variations (string/array/regex objects) are exercised; keeps schema compatibility tight.

Also applies to: 934-943, 971-999, 1079-1092, 1188-1199, 1240-1267

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

240-245: Don’t assign required/optional to index signatures.

Index signatures aren’t optional; pushing 'required' creates misleading 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')
+      }
+    }

334-343: Enable spacing diagnostics by passing a newline getter.

reportAllErrors lacks newlinesBetweenValueGetter, so missed/extra blank-line messages won't surface when newlinesBetween is set.

Apply:

+import { getLinesBetween } from '../utils/get-lines-between'
@@
   reportAllErrors<MessageIds>({
     sortNodesExcludingEslintDisabled,
     availableMessageIds,
+    newlinesBetweenValueGetter: (left, right) =>
+      getLinesBetween(sourceCode, left, right),
     sourceCode,
     options,
     context,
     nodes,
   })
🧹 Nitpick comments (45)
vite.config.ts (2)

9-16: Prefer named entry object for stable outputs

Use an entry object for explicit names; it plays nicer with d.ts generation and fileName callbacks.

-      entry: [
-        path.resolve(__dirname, 'index.ts'),
-        path.resolve(__dirname, 'utils', 'alphabet.ts'),
-      ],
+      entry: {
+        index: path.resolve(__dirname, 'index.ts'),
+        alphabet: path.resolve(__dirname, 'utils', 'alphabet.ts'),
+      },

14-15: ESM-only: drop unused name

name is only used for UMD/IIFE; for formats: ['es'] it’s redundant.

-      name: 'eslint-plugin-perfectionist',
rules/sort-object-types/types.ts (1)

167-182: Remove leftover 'multiline' selector mapping from AllowedModifiersPerSelector.

We no longer expose a 'multiline' selector; keeping it here is misleading.

[raise_n​i​n​o​r​_issue]

 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
 }
docs/content/rules/sort-array-includes.mdx (3)

4-4: Nit: “includes” (plural)

-shortDescription: Enforce sorted arrays before include method
+shortDescription: Enforce sorted arrays before includes method

199-205: Nit: grammar

-Specifies the sorting locales. Refer To [String.prototype.localeCompare() - locales](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/localeCompare#locales).
+Specifies the sorting locales. Refer to [String.prototype.localeCompare() - locales](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/localeCompare#locales).

489-493: Fix test link path

-- [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-objects.mdx (4)

278-286: newlinesBetween type/docs mismatch

Docs say type: number | 'ignore', but elsewhere (examples and tests in repo) accept 'never' | 'always' too. Update the type and bullets to include these string values to avoid confusion.

-<sub>type: `number | 'ignore'`</sub>
+<sub>type: `number | 'ignore' | 'never' | 'always'`</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.
+- `'never'` or `0` — No newlines are allowed.
+- `'always'` — Enforce one blank line between groups.
+- Any other positive number — Enforce this number of newlines between each group, and forbid newlines inside groups.

436-439: groups type should include inline newlinesBetween objects

Examples below place { newlinesBetween: ... } between groups. Reflect that in the declared type.

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

307-309: [DEPRECATED] ignorePattern: make flags optional for consistency

Other pattern types on this page use flags?: string. Adjust here too (even though deprecated) to avoid needless breaking in TS examples.

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

350-351: useConfigurationIf.declarationCommentMatchesPattern: flags should be optional

Align with elementNamePattern/elementValuePattern signatures.

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

54-68: Add missing default for useConfigurationIf for parity with other rules

Other rules set useConfigurationIf: {} in defaults. Including it here keeps behavior consistent and avoids undefined checks downstream.

 let defaultOptions: Required<Options[number]> = {
   fallbackSort: { type: 'unsorted' },
   specialCharacters: 'keep',
   partitionByNewLine: false,
   partitionByComment: false,
   newlinesBetween: 'ignore',
   type: 'alphabetical',
   ignoreAlias: false,
   customGroups: [],
   ignoreCase: true,
   locales: 'en-US',
   alphabet: '',
   order: 'asc',
   groups: [],
+  useConfigurationIf: {},
 }
test/rules/sort-named-imports.test.ts (1)

342-348: Confirmed message IDs exist; optional: make 'unknown' explicit in tests

  • Confirmed: message IDs are defined in rules/sort-named-imports.ts (lines 46–49) and mapped to error constants (lines 182–185, 219–222) — tests using 'unexpectedNamedImportsGroupOrder' are valid.
  • Optional: change the test assertion to ['type-import','unknown'] for clarity; docs don't show an explicit "auto-append unknown" mention.
test/rules/sort-object-types.test.ts (3)

2210-2237: Dual configuration with useConfigurationIf: allNamesMatchPattern

Good demonstration of multiple configurations with selective matching. Consider adding one negative case where no config matches to assert fallback selection.

Also applies to: 4778-4806, 7289-7317


2370-2425: New: declarationCommentMatchesPattern coverage

Great addition validating declaration comment matching. Consider adding a case with multiple leading comments where only one matches to confirm nearest/any precedence.


2100-2156: Inline members fix output formatting

Ensuring consistent semicolons/commas in “inline” object type members is good. If available, add one snapshot to guard against regressions in whitespace.

Also applies to: 4668-4724, 7179-7235

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

335-339: Include newlinesBetween object in groups type

Examples include { newlinesBetween: ... } entries, but the declared type omits this union.

Apply this diff:

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

575-577: Fix test source link path

Tests live under test/rules. Update link to avoid 404.

Apply this diff:

-- [Test source](https://github.com/azat-io/eslint-plugin-perfectionist/blob/main/test/sort-jsx-props.test.ts)
+- [Test source](https://github.com/azat-io/eslint-plugin-perfectionist/blob/main/test/rules/sort-jsx-props.test.ts)
docs/content/rules/sort-interfaces.mdx (4)

371-383: Regex example typo in declarationMatchesPattern

'*Metadata$' is not a valid regex. Use '.*Metadata$' (or 'Metadata$') to match suffix “Metadata”.

Apply this diff:

-      useConfigurationIf: {
-        declarationMatchesPattern: '*Metadata$',
-      },
+      useConfigurationIf: {
+        declarationMatchesPattern: '.*Metadata$',
+      },

408-411: Include newlinesBetween object in groups type

Examples show { newlinesBetween: ... } but the union isn’t in the declared type.

Apply this diff:

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

512-520: Close the interface code block

The second example is missing the closing brace, which breaks copy-paste.

Apply this diff:

   // 'required-method'
   method(): string
+}

765-766: Fix test source link path

Point to test/rules to match repo layout.

Apply this diff:

-- [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)
test/rules/sort-named-exports.test.ts (2)

166-169: Explicitly include unknown in groups for clarity (optional)

Some tests rely on implicit unknown injection. Consider adding groups: ['type-export', 'unknown'] here to avoid ambiguity across rules that don’t auto-append unknown.

If you prefer implicit behavior, please confirm unknown is auto-added by the rule’s option resolution for sort-named-exports.


1537-1538: Mirror earlier nit (optional)

Same optional clarity nit: consider groups: ['type-export', 'unknown'].

docs/content/rules/sort-object-types.mdx (3)

731-733: Fix broken “Test source” link path

Repository path includes test/rules/. Update link to avoid 404.

-- [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)

335-343: Correct regex example

'*Metadata$' isn’t a valid regex; use '.*Metadata$'.

-        declarationMatchesPattern: '*Metadata$',
+        declarationMatchesPattern: '.*Metadata$',

671-676: Remove deprecated ignorePattern from usage snippets (v5)

PR goals say deprecated options are eliminated in v5. The usage block still shows ignorePattern. Suggest removing for consistency (do the same in the Legacy Config block below).

-                  ignorePattern: [],

If ignorePattern is intentionally kept in v5 as deprecated-but-supported, keep it and add a deprecation note near the snippet.

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

165-176: Enable spacing diagnostics by passing a newline getter

Without newlinesBetweenValueGetter, missed/extra spacing messages won’t trigger. Import getLinesBetween and pass it to reportAllErrors.

+import { getLinesBetween } from '../utils/get-lines-between'
@@
-      reportAllErrors<MessageId>({
+      reportAllErrors<MessageId>({
         availableMessageIds: {
           missedSpacingBetweenMembers: 'missedSpacingBetweenNamedImports',
           extraSpacingBetweenMembers: 'extraSpacingBetweenNamedImports',
           unexpectedGroupOrder: 'unexpectedNamedImportsGroupOrder',
           unexpectedOrder: 'unexpectedNamedImportsOrder',
         },
+        newlinesBetweenValueGetter: (left, right) =>
+          getLinesBetween(sourceCode, left, right),
         sortNodesExcludingEslintDisabled,
         sourceCode,
         options,
         context,
         nodes,
       })
test/rules/sort-decorators.test.ts (3)

803-850: Negative regex grouping — nice edge case

Covers negative lookahead well. Optional: add a case‑insensitive negative pattern to ensure flags are honored in exclusion paths too.


446-469: Tiny wording nit in test fixtures: “Not a JSDoc comment”

For readability, add a space in “a JSDoc”. No behavioral change.

Apply this diff:

-            // Not aJSDoc comment
+            // Not a JSDoc comment

Also applies to: 2881-2903


1412-1531: partitionByNewLine — canonical; fix doc/test spelling

Schema, types, defaults and rule options use partitionByNewLine. Update human-readable/test strings that use 'partitionByNewline' (e.g. test/utils/validate-newlines-and-partition-configuration.test.ts) to 'partitionByNewLine' to avoid confusion.

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

185-189: Extend groups type to allow inline newlinesBetween objects.

Your examples use objects between groups; reflect in the declared type.

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

416-418: Verify “Test source” link path.

Repo seems to use test/rules/*.test.ts. Confirm the target exists or update the URL accordingly.

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

50-58: Add partitionByComment to Options for parity with other sorting rules.

If this rule supports partitions by comment like others, expose it in the type.

-    /** Controls the placement of newlines between different groups of JSX props. */
+    /** Controls the placement of newlines between different groups of JSX props. */
     newlinesBetween: NewlinesBetweenOption
+    /** Partition props by comments (block/line/regex). */
+    partitionByComment: PartitionByCommentOption

And add the import:

-import type {
+import type {
   NewlinesBetweenOption,
   CustomGroupsOption,
   CommonOptions,
   GroupsOptions,
   RegexOption,
+  PartitionByCommentOption,
 } from '../../types/common-options'
test/rules/sort-imports.test.ts (5)

1462-1475: DRY up repeated customGroups fixtures.

This A/B groups fixture repeats many times across suites. Extract a shared constant to reduce noise and review surface.

-              customGroups: [
-                {
-                  groupName: 'unusedGroup',
-                  elementNamePattern: 'X',
-                },
-                {
-                  elementNamePattern: 'a',
-                  groupName: 'a',
-                },
-                {
-                  elementNamePattern: 'b',
-                  groupName: 'b',
-                },
-              ],
+              customGroups: AB_GROUPS_WITH_UNUSED,

Add near the top of the file (or a test utils module):

const AB_GROUPS_WITH_UNUSED = [
  { groupName: 'unusedGroup', elementNamePattern: 'X' },
  { groupName: 'a', elementNamePattern: 'a' },
  { groupName: 'b', elementNamePattern: 'b' },
] as const

1613-1626: Repeat of A/B groups fixture.

Once a shared constant is introduced, replace this inline array too.


5105-5118: Same A/B customGroups duplication in “natural”.

Apply the shared fixture here as well.


11263-11308: Huge customGroups matrix: consider a builder to cut repetition.

Generating these regex-backed groups via a tiny helper (e.g., group('validators', '^~/validators/.+')) will make additions safer and reduce copy/paste risk.

Example helper:

const group = (name: string, pattern: string, modifiers: readonly ('type'|'value')[] = []) =>
  ({ groupName: name, elementNamePattern: pattern, modifiers }) as const

11356-11426: Large invalid case mirrors the valid one—good negative coverage.

If refactoring with a builder, reuse it here to keep valid/invalid in lockstep.

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

329-336: Good move to array-based customGroups.

The shape matches the new schema (elementNamePattern + groupName). Consider adding one negative test with an unknown group in groups to assert the validator error path.


1242-1267: useConfigurationIf cascade looks right.

Two-option array verifies conditional config vs default. Consider one additional case where neither predicate matches to assert default rule behavior.

rules/sort-decorators.ts (2)

254-283: Pass newline getter to unlock spacing diagnostics.

As with other rules, reportAllErrors benefits from newlinesBetweenValueGetter for missed/extra blank-line messages.

Apply:

+import { getLinesBetween } from '../utils/get-lines-between'
@@
   reportAllErrors<MessageId>({
     availableMessageIds: {
       missedSpacingBetweenMembers: 'missedSpacingBetweenDecorators',
       extraSpacingBetweenMembers: 'extraSpacingBetweenDecorators',
       unexpectedGroupOrder: 'unexpectedDecoratorsGroupOrder',
       unexpectedOrder: 'unexpectedDecoratorsOrder',
     },
     ignoreFirstNodeHighestBlockComment: true,
+    newlinesBetweenValueGetter: (left, right) =>
+      getLinesBetween(sourceCode, left, right),
     sortNodesExcludingEslintDisabled,
     sourceCode,
     options,
     context,
     nodes,
   })

141-156: Parameter decorators detection: broaden coverage.

The Identifier + FunctionExpression check may miss function declarations and constructor parameters. Recommend tests and minor broadening.

Add tests for:

  • function declaration parameters
  • class constructor parameters

If gaps appear, consider detecting decorator.parent kinds beyond Identifier in parameter positions.

utils/make-newlines-between-fixes.ts (3)

156-164: Avoid .at(...) here; use tuple indexing to prevent accidental undefined and implicit “start=0” slices.

.at(1) on a tuple is typed as number | undefined; passing that to slice can silently coerce to 0. Index directly to express intent and keep types strict.

-  let nextNodeRangeStart = getNodeRange({
-    node: nextSortingNode.node,
-    sourceCode,
-  }).at(0)!
+  let [nextNodeRangeStart] = getNodeRange({
+    node: nextSortingNode.node,
+    sourceCode,
+  })
@@
-  let rangeToReplace: [number, number] = [
-    currentNodeRange.at(1)!,
-    nextNodeRangeStart,
-  ]
-  let textBetweenNodes = sourceCode.text.slice(
-    currentNodeRange.at(1),
-    nextNodeRangeStart,
-  )
+  let rangeToReplace: [number, number] = [currentNodeRange[1], nextNodeRangeStart]
+  let textBetweenNodes = sourceCode.text.slice(currentNodeRange[1], nextNodeRangeStart)

Also applies to: 142-146


28-31: Docstring says “Optional custom groups” but the property is required.

Align the comment to avoid confusion for integrators and maintainers.

-    /** Optional custom groups configuration. */
-    customGroups: CustomGroupsOption
+    /** Custom groups configuration (required). */
+    customGroups: CustomGroupsOption

112-118: Micro‑opt: avoid repeated getGroupIndex calls in the loop.

Precompute group indices for sortedNodes once and reuse. Small win, clearer intent.

-  for (let i = 0; i < sortedNodes.length - 1; i++) {
+  let groupIndexById = new Map(sortedNodes.map(n => [n.id, getGroupIndex(options.groups, n)]))
+  for (let i = 0; i < sortedNodes.length - 1; i++) {
@@
-    let nodeGroupIndex = getGroupIndex(options.groups, sortedSortingNode)
-    let nextNodeGroupIndex = getGroupIndex(
-      options.groups,
-      nextSortedSortingNode,
-    )
+    let nodeGroupIndex = groupIndexById.get(sortedSortingNode.id)!
+    let nextNodeGroupIndex = groupIndexById.get(nextSortedSortingNode.id)!

(Adjust the key if SortingNode uses a different stable identity.)

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 979f8b3 and 73dd08b.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (79)
  • 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 (5 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 (5 hunks)
  • docs/content/rules/sort-sets.mdx (3 hunks)
  • package.json (4 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-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-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 (7 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 (10 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 (10 hunks)
  • rules/sort-objects/types.ts (5 hunks)
  • rules/sort-switch-case.ts (1 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-exports.test.ts (0 hunks)
  • test/rules/sort-heritage-clauses.test.ts (5 hunks)
  • test/rules/sort-imports.test.ts (25 hunks)
  • test/rules/sort-interfaces.test.ts (18 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)
  • test/rules/sort-objects.test.ts (31 hunks)
  • test/rules/sort-sets.test.ts (3 hunks)
  • test/utils/compute-group.test.ts (3 hunks)
  • test/utils/filter-options-by-all-names-match.test.ts (1 hunks)
  • test/utils/filter-options-by-declaration-comment-matches.test.ts (1 hunks)
  • test/utils/get-custom-groups-compare-options.test.ts (0 hunks)
  • test/utils/get-matching-context-options.test.ts (0 hunks)
  • test/utils/get-newlines-between-option.test.ts (4 hunks)
  • types/common-options.ts (0 hunks)
  • utils/common-json-schemas.ts (0 hunks)
  • utils/compute-group.ts (4 hunks)
  • utils/filter-options-by-all-names-match.ts (3 hunks)
  • utils/filter-options-by-declaration-comment-matches.ts (1 hunks)
  • utils/get-comment-above-that-should-exist.ts (2 hunks)
  • utils/get-custom-groups-compare-options.ts (2 hunks)
  • utils/get-newlines-between-errors.ts (1 hunks)
  • utils/get-newlines-between-option.ts (1 hunks)
  • utils/make-comment-above-fixes.ts (2 hunks)
  • utils/make-fixes.ts (2 hunks)
  • utils/make-newlines-between-fixes.ts (1 hunks)
  • utils/report-all-errors.ts (0 hunks)
  • utils/validate-generated-groups-configuration.ts (5 hunks)
  • vite.config.ts (1 hunks)
💤 Files with no reviewable changes (11)
  • test/utils/get-matching-context-options.test.ts
  • test/rules/sort-exports.test.ts
  • docs/content/rules/sort-exports.mdx
  • types/common-options.ts
  • rules/sort-exports/types.ts
  • utils/common-json-schemas.ts
  • test/utils/get-custom-groups-compare-options.test.ts
  • utils/report-all-errors.ts
  • rules/sort-array-includes/types.ts
  • docs/content/rules/sort-named-imports.mdx
  • docs/content/rules/sort-named-exports.mdx
🚧 Files skipped from review as they are similar to previous changes (33)
  • rules/sort-switch-case.ts
  • rules/sort-classes.ts
  • rules/sort-maps.ts
  • rules/sort-named-exports/types.ts
  • docs/content/rules/sort-imports.mdx
  • utils/filter-options-by-declaration-comment-matches.ts
  • rules/sort-variable-declarations.ts
  • docs/content/rules/sort-intersection-types.mdx
  • utils/get-custom-groups-compare-options.ts
  • rules/sort-modules.ts
  • test/utils/get-newlines-between-option.test.ts
  • rules/sort-union-types.ts
  • test/utils/filter-options-by-declaration-comment-matches.test.ts
  • rules/sort-named-imports/types.ts
  • rules/sort-interfaces.ts
  • rules/sort-exports.ts
  • rules/sort-decorators/types.ts
  • test/utils/filter-options-by-all-names-match.test.ts
  • rules/sort-intersection-types.ts
  • rules/sort-imports/types.ts
  • utils/make-comment-above-fixes.ts
  • test/rules/sort-object-types/get-custom-groups-compare-options.test.ts
  • utils/get-newlines-between-errors.ts
  • utils/compute-group.ts
  • utils/make-fixes.ts
  • utils/get-newlines-between-option.ts
  • package.json
  • utils/get-comment-above-that-should-exist.ts
  • rules/sort-objects/types.ts
  • rules/sort-objects.ts
  • docs/content/rules/sort-decorators.mdx
  • rules/sort-heritage-clauses/types.ts
  • docs/content/rules/sort-sets.mdx
🧰 Additional context used
🧬 Code graph analysis (15)
test/rules/sort-imports.test.ts (1)
rules/sort-imports/types.ts (1)
  • Options (29-141)
rules/sort-enums.ts (3)
rules/sort-array-includes.ts (1)
  • defaultOptions (60-74)
rules/sort-enums/types.ts (1)
  • Options (20-68)
utils/common-json-schemas.ts (1)
  • buildCustomGroupsArrayJsonSchema (302-351)
rules/sort-named-exports.ts (5)
rules/sort-array-includes.ts (1)
  • defaultOptions (60-74)
rules/sort-named-exports/types.ts (2)
  • Options (26-66)
  • SortNamedExportsSortingNode (95-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/validate-generated-groups-configuration.ts (1)
types/common-options.ts (1)
  • CustomGroupsOption (103-140)
rules/sort-named-imports.ts (5)
rules/sort-array-includes.ts (1)
  • defaultOptions (60-74)
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)
utils/make-newlines-between-fixes.ts (1)
types/common-options.ts (2)
  • NewlinesBetweenOption (203-226)
  • CustomGroupsOption (103-140)
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-object-types.ts (5)
rules/sort-object-types/types.ts (4)
  • Options (28-112)
  • SortObjectTypesSortingNode (386-394)
  • Selector (147-151)
  • Modifier (159-159)
utils/common-json-schemas.ts (1)
  • regexJsonSchema (219-228)
utils/matches.ts (1)
  • matches (39-60)
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-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-decorators.ts (7)
rules/sort-decorators/types.ts (1)
  • Options (16-29)
utils/common-json-schemas.ts (3)
  • buildCustomGroupsArrayJsonSchema (302-351)
  • partitionByNewLineJsonSchema (268-272)
  • 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-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-imports.ts (8)
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)
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-jsx-props.ts (4)
rules/sort-jsx-props/types.ts (1)
  • Options (24-71)
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-heritage-clauses.ts (11)
rules/sort-heritage-clauses/types.ts (1)
  • Options (14-22)
utils/common-json-schemas.ts (5)
  • buildCustomGroupsArrayJsonSchema (302-351)
  • partitionByNewLineJsonSchema (268-272)
  • partitionByCommentJsonSchema (241-262)
  • 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 (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/types.ts (1)
types/common-options.ts (1)
  • CustomGroupsOption (103-140)
rules/sort-object-types/get-custom-groups-compare-options.ts (2)
rules/sort-interfaces.ts (1)
  • Options (12-12)
rules/sort-object-types/types.ts (1)
  • Options (28-112)

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.

Comment on lines +149 to +162
reportAllErrors<MessageId>({
availableMessageIds: {
missedSpacingBetweenMembers: 'missedSpacingBetweenImportAttributes',
extraSpacingBetweenMembers: 'extraSpacingBetweenImportAttributes',
unexpectedGroupOrder: 'unexpectedImportAttributesGroupOrder',
unexpectedOrder: 'unexpectedImportAttributesOrder',
},
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

Missing newlinesBetweenValueGetter in reportAllErrors call.

The reportAllErrors call is missing the newlinesBetweenValueGetter parameter, which will prevent spacing diagnostics from working correctly.

+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,
         })
📝 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
reportAllErrors<MessageId>({
availableMessageIds: {
missedSpacingBetweenMembers: 'missedSpacingBetweenImportAttributes',
extraSpacingBetweenMembers: 'extraSpacingBetweenImportAttributes',
unexpectedGroupOrder: 'unexpectedImportAttributesGroupOrder',
unexpectedOrder: 'unexpectedImportAttributesOrder',
},
sortNodesExcludingEslintDisabled:
createSortNodesExcludingEslintDisabled(nodes),
sourceCode,
options,
context,
nodes,
})
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,
})
🤖 Prompt for AI Agents
In rules/sort-import-attributes.ts around lines 149 to 162, the call to
reportAllErrors is missing the newlinesBetweenValueGetter parameter which
prevents spacing diagnostics from working; add the newlinesBetweenValueGetter
argument (the existing function/variable in this module that computes required
newlines between values) to the reportAllErrors call so it receives
newlinesBetweenValueGetter along with the other parameters.

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,
+        }
   }

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-enums.mdx (1)

409-411: Update Test source link to the new path.

The file lives under test/rules now.

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

57-71: Use const for immutable defaults.

defaultOptions is never reassigned; prefer const.

-let defaultOptions: Required<Options[number]> = {
+const defaultOptions: Required<Options[number]> = {

110-118: Capture dependencies from computed enum member access (Enum['A']).

Currently only Identifier properties are collected. Add support for computed string-literal properties to avoid missing intra-enum edges.

-          if (
-            node.type === 'MemberExpression' &&
-            node.object.type === 'Identifier' &&
-            node.object.name === enumName &&
-            node.property.type === 'Identifier'
-          ) {
-            dependencies.push(node.property.name)
+          if (
+            node.type === 'MemberExpression' &&
+            node.object.type === 'Identifier' &&
+            node.object.name === enumName
+          ) {
+            if (!node.computed && node.property.type === 'Identifier') {
+              dependencies.push(node.property.name)
+            } else if (node.computed && node.property.type === 'Literal') {
+              if (typeof node.property.value !== 'undefined' && node.property.value !== null) {
+                dependencies.push(String(node.property.value))
+              }
+            }
           } else if (node.type === 'Identifier') {
             dependencies.push(node.name)
           }

408-426: Confirm intent: overriding type to 'natural' when sorting numeric enums by value.

When isNumericEnum and sortByValue !== 'never', type is forced to 'natural', overriding user-specified 'type' (including 'unsorted'). If intended, consider an explicit note in docs and a test for type: 'unsorted' + ifNumericEnum.

Would you like me to add a test case covering:

  • type: 'unsorted', sortByValue: 'ifNumericEnum' → numeric sort by value wins?
test/rules/sort-enums.test.ts (2)

1575-1591: Great coverage for sortByValue semantics; consider adding an 'unsorted' type case.

Add a case: type 'unsorted' + sortByValue 'ifNumericEnum' to assert value-based ordering still applies.

I can draft that test if helpful.

Also applies to: 3009-3050


4999-5005: Minor consistency nit: test descriptions vs. options.

The description says “sorts numeric enums by value when sortByValue is enabled” but uses 'always' (explicit). Consider a companion case for 'ifNumericEnum' in the same block for symmetry.

Also applies to: 5043-5049

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between baade3e and fa55de3.

📒 Files selected for processing (4)
  • docs/content/rules/sort-enums.mdx (3 hunks)
  • rules/sort-enums.ts (9 hunks)
  • rules/sort-enums/types.ts (1 hunks)
  • test/rules/sort-enums.test.ts (19 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
rules/sort-enums.ts (5)
rules/sort-enums/types.ts (1)
  • Options (20-60)
utils/common-json-schemas.ts (1)
  • buildCustomGroupsArrayJsonSchema (302-351)
utils/compare.ts (1)
  • NodeValueGetterFunction (19-19)
utils/unreachable-case-error.ts (1)
  • UnreachableCaseError (31-43)
types/common-options.ts (1)
  • TypeOption (158-187)
🔇 Additional comments (8)
rules/sort-enums.ts (4)

338-365: Node value getter logic looks solid and exhaustiveness is enforced.

The switch correctly gates value-based sorting and uses UnreachableCaseError for safety. LGTM.


263-271: Schema updates align with new customGroups array DSL and sortByValue enum.

The JSON schema matches the new API surface. LGTM.


299-309: Numeric expression evaluation: graceful null on unknowns and safe ops.

Early null checks and handled operators are appropriate; defaults return null. LGTM.

Also applies to: 331-335, 367-385, 391-405


144-148: Normalize enum member names to string (prevents dependency/group mismatches).

member.id.value can be non-string for literal names. Convert at the source so elementName, dependencyNames, and custom-group matching stay string-typed and consistent.

-          let name =
-            member.id.type === 'Literal'
-              ? member.id.value
-              : sourceCode.getText(member.id)
+          const name =
+            member.id.type === 'Literal'
+              ? String(member.id.value)
+              : sourceCode.getText(member.id)

Also applies to: 175-180

test/rules/sort-enums.test.ts (4)

66-74: Switch to string-literal enum keys: looks good.

Test updates reflect string-literal member names and align with rule behavior. LGTM.

Also applies to: 90-104, 1647-1651, 1667-1680, 3206-3239


4923-4945: Potential duplicate enum member name ('m').

Two members named 'm' may be parser-accepted but are illegal in TS. If the parser allows it, fine; otherwise this test could fail on some setups.

Would you like me to rewrite with unique keys while preserving the numeric-expression coverage?


5280-5313: Disable-comment scenarios: strong coverage.

Good validation of interaction between rule fixes and eslint-disable lines/blocks.

Also applies to: 5710-5791, 5907-5940


5316-5347: Partition vs. dependency precedence test is valuable.

Confirms dependencies override partitions. Nicely scoped.

When this setting is `true`, numeric enums will have their values sorted numerically regardless of the `type` setting.

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 wording: sortByValue is not boolean.

“When this setting is true” is outdated. Clarify behavior for 'always' and 'ifNumericEnum'.

-When this setting is `true`, numeric enums will have their values sorted numerically regardless of the `type` setting.
+When set to "always", members are sorted by their values. When set to "ifNumericEnum", members are sorted by their values only if the enum is numeric; otherwise names are used, regardless of the `type` setting.
📝 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
When this setting is `true`, numeric enums will have their values sorted numerically regardless of the `type` setting.
When set to "always", members are sorted by their values. When set to "ifNumericEnum", members are sorted by their values only if the enum is numeric; otherwise names are used, regardless of the `type` setting.
🤖 Prompt for AI Agents
In docs/content/rules/sort-enums.mdx around lines 181 to 182, update the
sentence that currently reads "When this setting is `true`, numeric enums will
have their values sorted numerically regardless of the `type` setting." because
sortByValue is not boolean; replace it with wording that explains the two valid
options, e.g. state that when sortByValue is "always" enum values are always
sorted numerically, and when it's "ifNumericEnum" numeric enums are sorted
numerically but non-numeric enums are unaffected, making the behavior with
respect to the `type` setting explicit.

Comment on lines 28 to 35
/**
* Whether to sort enum members by their values instead of names. When true,
* compares enum values; when false, compares enum member names.
*
* @default ifNumericEnum
*/
sortByValue: 'ifNumericEnum' | 'always' | 'never'

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 the JSDoc to reflect the new string-valued option.

The description still talks about a boolean toggle (“When true/false”), but sortByValue now exposes 'ifNumericEnum' | 'always' | 'never'. The generated docs (and consumers reading the types) will be wrong unless we document what each literal means and when to use it. Please update the block accordingly.

-    /**
-     * Whether to sort enum members by their values instead of names. When true,
-     * compares enum values; when false, compares enum member names.
-     *
-     * @default ifNumericEnum
-     */
-    sortByValue: 'ifNumericEnum' | 'always' | 'never'
+    /**
+     * Controls when enum members should be ordered by their values instead of names.
+     * - `'always'` compares enum member values for every enum.
+     * - `'never'` keeps name-based ordering regardless of values.
+     * - `'ifNumericEnum'` sorts by value only when every member has a numeric initializer.
+     *
+     * @default ifNumericEnum
+     */
+    sortByValue: 'ifNumericEnum' | 'always' | 'never'
📝 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
/**
* Whether to sort enum members by their values instead of names. When true,
* compares enum values; when false, compares enum member names.
*
* @default ifNumericEnum
*/
sortByValue: 'ifNumericEnum' | 'always' | 'never'
/**
* Controls when enum members should be ordered by their values instead of names.
* - `'always'` compares enum member values for every enum.
* - `'never'` keeps name-based ordering regardless of values.
* - `'ifNumericEnum'` sorts by value only when every member has a numeric initializer.
*
* @default ifNumericEnum
*/
sortByValue: 'ifNumericEnum' | 'always' | 'never'
🤖 Prompt for AI Agents
In rules/sort-enums/types.ts around lines 28 to 35, the JSDoc still describes a
boolean toggle but the type is now a string union; update the comment to remove
"When true/false" language and instead document each allowed literal
('ifNumericEnum' | 'always' | 'never') with a one-line explanation for each
(e.g., 'ifNumericEnum' = sort by value only for numeric enums, 'always' = always
sort by value, 'never' = never sort by value), and include the default behavior
(i.e., @default ifNumericEnum) so generated docs and type consumers correctly
understand the new options.

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.

Comment on lines +163 to +167
parentNode:
| TSESTree.TSTypeAliasDeclaration
| TSESTree.TSInterfaceDeclaration
| null
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

Signature includes TSInterfaceDeclaration but no caller provides it.

The parentNode parameter accepts TSInterfaceDeclaration, but no visitor currently calls sortObjectTypeElements with an interface parent. This is consistent with the missing TSInterfaceBody visitor noted above.

If interface support is not needed, remove TSInterfaceDeclaration from the union:

 parentNode:
   | TSESTree.TSTypeAliasDeclaration
-  | TSESTree.TSInterfaceDeclaration
   | null

Otherwise, add the missing TSInterfaceBody visitor as noted in the previous comment.

📝 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
parentNode:
| TSESTree.TSTypeAliasDeclaration
| TSESTree.TSInterfaceDeclaration
| null
parentNode:
| TSESTree.TSTypeAliasDeclaration
| null
🤖 Prompt for AI Agents
In rules/sort-object-types.ts around lines 163 to 166, the parentNode union
includes TSESTree.TSInterfaceDeclaration even though no visitor ever calls
sortObjectTypeElements with an interface parent; either remove
TSInterfaceDeclaration from the parentNode union if interface support is not
required, or implement the missing TSInterfaceBody visitor that calls
sortObjectTypeElements for interface bodies so interfaces are actually
handled—update the type union or add the visitor accordingly and ensure
tests/usage reflect the chosen approach.

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.


export default eslintConfig({
extends: eslintPlugin,
extends: eslintPlugin.configs.recommended,
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

Verify the correct flat config property name.

Based on the retrieved learnings, eslint-plugin-eslint-plugin v7.0.0 provides flat config exports as configs["flat/recommended"]. Since this file uses flat config format (indicated by satisfies Promise<Linter.Config[]>), verify that configs.recommended is the correct property or if it should be configs["flat/recommended"].

Run the following script to verify the available config exports:

Based on learnings.


🏁 Script executed:

#!/bin/bash
# Description: Check the available config exports from eslint-plugin-eslint-plugin

# Check if package.json or documentation mentions the correct config export
rg -n "configs\[" --type=md --type=json -g '!**/node_modules/**' -C 3

# Check if there are any other files using this import pattern
rg -n "eslintPlugin\.configs" --type=ts --type=js -g '!**/node_modules/**' -C 2

# Examine package.json to understand exports
cat package.json | jq '.devDependencies["eslint-plugin-eslint-plugin"]'

Length of output: 306


Run the following script to confirm the correct flat config export names in the plugin’s README:


🏁 Script executed:

#!/bin/bash
npm view [email protected] readme | rg -n 'configs\[' -C2
npm view [email protected] readme | rg -n 'flat/recommended' -C2

Length of output: 234


Use the correct flat config key
In eslint.config.ts (line 7), replace

extends: eslintPlugin.configs.recommended,

with

extends: eslintPlugin.configs['rules-recommended'],
🤖 Prompt for AI Agents
In eslint.config.ts around line 7, the config uses the incorrect flat-config key
"extends: eslintPlugin.configs.recommended"; update this to use the correct flat
config key by replacing that entry with the 'rules-recommended' key from
eslintPlugin.configs (i.e., use eslintPlugin.configs['rules-recommended'] as the
extends value) so the plugin's recommended rules are applied 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: 4

Caution

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

⚠️ Outside diff range comments (2)
rules/sort-jsx-props/types.ts (1)

94-118: Fix stale selector docs to match single 'prop' support.

Comments still promise 'multiline' / 'shorthand' selector values even though the schema and Selector type now expose 'prop' only. Please align the JSDoc so consumers don’t configure unsupported selectors.

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

572-579: Update the documented customGroups type.

The snippet still advertises the deprecated object-map shape ({ [groupName: string]: string | string[] }), but the rule now expects an array of definition objects. Keeping this text will cause copy-paste configs to fail in v5.

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

Also ensure the surrounding prose reflects the array-based structure (matching the example immediately below).

♻️ Duplicate comments (20)
docs/content/rules/sort-objects.mdx (2)

345-364: Fix the RGB regex example again.

'^r|g|b$' still expands to (^r) or g or (b$), so it matches keys you didn’t intend. Please keep the grouped, anchored version that was previously applied.

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

399-405: Replace the invalid declaration regex.

'*metadata$' is not a valid regular expression (leading * triggers “nothing to repeat”). Copying this snippet will throw at runtime. Please restore the '.*metadata$' version.

-        declarationMatchesPattern: '*metadata$',
+        declarationMatchesPattern: '.*metadata$',
rules/sort-objects.ts (1)

562-592: Return the correct parent type for nested properties

getObjectParent still reports type: 'VariableDeclarator' even when the nearest ancestor is a Property. That makes declarationMatchesPattern / declarationCommentMatchesPattern fire for nested object literals and breaks the intended guardrails we discussed earlier. Please preserve the real ancestor kind so only actual declarators run through those filters.

 }):
-  | {
-      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
     }
@@
   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,
+    }
   }
rules/sort-import-attributes.ts (1)

7-162: Wire newlinesBetweenValueGetter so spacing errors fire

Without a newlinesBetweenValueGetter, getNewlinesBetweenErrors can’t compute spacing and the rule silently skips missedSpacingBetweenMembers/extraSpacingBetweenMembers, so the documented newline guarantees never apply. Please hook up the standard helper.

 import {
   buildCustomGroupsArrayJsonSchema,
   partitionByCommentJsonSchema,
   partitionByNewLineJsonSchema,
   newlinesBetweenJsonSchema,
   commonJsonSchemas,
   groupsJsonSchema,
 } from '../utils/common-json-schemas'
+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,
index.ts (1)

133-166: Use const + satisfies for configs

Replace export let configs = { ... } with export const configs = { ... } satisfies Record<string, Linter.Config | Linter.LegacyConfig> to make the object immutable and statically validated.

Apply this diff:

-export let configs = {
+export const configs = {
   'recommended-alphabetical-legacy': createLegacyConfig({
     type: 'alphabetical',
     order: 'asc',
   }),
   'recommended-line-length-legacy': createLegacyConfig({
     type: 'line-length',
     order: 'desc',
   }),
   'recommended-natural-legacy': createLegacyConfig({
     type: 'natural',
     order: 'asc',
   }),
   'recommended-custom-legacy': createLegacyConfig({
     type: 'custom',
     order: 'asc',
   }),
   'recommended-alphabetical': createConfig({
     type: 'alphabetical',
     order: 'asc',
   }),
   'recommended-line-length': createConfig({
     type: 'line-length',
     order: 'desc',
   }),
   'recommended-natural': createConfig({
     type: 'natural',
     order: 'asc',
   }),
   'recommended-custom': createConfig({
     type: 'custom',
     order: 'asc',
   }),
-}
+} satisfies Record<string, Linter.Config | Linter.LegacyConfig>
test/rules/sort-imports.test.ts (1)

4312-4378: @typescript-eslint/no-unsafe-call is still firing on these dedent templates

The lint failure called out earlier hasn’t been addressed—dedent\...`is still used without a suppression, so@typescript-eslint/no-unsafe-callwill continue to break the build on these lines. Please either drop in the one-line disable comments before eachdedentinvocation or switch to a typed alternative (e.g.,dedent(String.raw`...`)`) as previously suggested.

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

329-337: Restore spacing diagnostics by wiring newlinesBetweenValueGetter.

reportAllErrors still isn’t told how to compute blank lines, so every newlinesBetween violation silently passes. Add the getter (and its import) so spacing errors fire again.

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

25-25: Fix test title: "import" → "export"

This test exercises export attributes, but the title says "import attributes".

Apply this diff:

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

50-50: Fix test title: "import" → "export"

This test exercises multiline export attributes, but the title says "import attributes".

Apply this diff:

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

276-276: Fix test title: "import" → "export"

This test exercises export attributes, but the title says "import attributes".

Apply this diff:

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

301-301: Fix test title: "import" → "export"

This test exercises multiline export attributes, but the title says "import attributes".

Apply this diff:

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

551-551: Fix test title: "import" → "export"

This test exercises export attributes, but the title says "import attributes".

Apply this diff:

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

576-576: Fix test title: "import" → "export"

This test exercises multiline export attributes, but the title says "import attributes".

Apply this diff:

-    it('sorts multiline import attributes', async () => {
+    it('sorts multiline export attributes', async () => {
docs/content/rules/sort-heritage-clauses.mdx (3)

152-159: Fix terminology: "decorators" → "heritage clauses"; make flags optional

The description incorrectly references "class decorators" and the RegExpPattern examples require flags when they should be optional.

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.

-- `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.

168-176: Expand newlinesBetween type and document 'always'/'never'

The documented type is incomplete and the bullets don't describe 'always' and 'never' options.

Apply this diff:

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

 Specifies how to handle newlines between groups.

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

265-273: Add 'custom' to type union; expand newlinesInside type

CustomGroupDefinition is missing 'custom' in the type field and newlinesInside should accept 'always' | 'never' in addition to 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
+  newlinesInside?: 'always' | 'never' | number
   elementNamePattern?: string | string[] | { pattern: string; flags?: string } | { pattern: string; flags?: string }[]
 }
docs/content/rules/sort-decorators.mdx (3)

255-263: Expand newlinesBetween type and document 'always'/'never'

The type annotation and bullets are incomplete.

Apply this diff:

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

 Specifies how to handle newlines between groups.

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

352-359: Correct CustomGroupDefinition typings

fallbackSort.type should be a specific union, and newlinesInside should accept 'always' | 'never' | number.

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
   elementNamePattern?: string | string[] | { pattern: string; flags?: string } | { pattern: string; flags?: string }[]
 }

367-378: Correct CustomGroupAnyOfDefinition typings

Same typing issues as CustomGroupDefinition.

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 }[]
   }>
 }
rules/sort-heritage-clauses.ts (1)

193-206: Provide newlinesBetweenValueGetter to enable spacing error reporting

The reportAllErrors call includes spacing-related message IDs (missedSpacingBetweenMembers, extraSpacingBetweenMembers) but doesn't provide the required newlinesBetweenValueGetter parameter. This will prevent spacing violations from being detected.

Apply this diff:

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

   reportAllErrors<MessageId>({
     availableMessageIds: {
       missedSpacingBetweenMembers: 'missedSpacingBetweenHeritageClauses',
       extraSpacingBetweenMembers: 'extraSpacingBetweenHeritageClauses',
       unexpectedGroupOrder: 'unexpectedHeritageClausesGroupOrder',
       unexpectedOrder: 'unexpectedHeritageClausesOrder',
     },
     sortNodesExcludingEslintDisabled:
       createSortNodesExcludingEslintDisabled(nodes),
+    newlinesBetweenValueGetter: (left, right) =>
+      getLinesBetween(sourceCode, left, right),
     sourceCode,
     options,
     context,
     nodes,
   })
🧹 Nitpick comments (1)
docs/content/rules/sort-object-types.mdx (1)

351-369: LGTM! Clear documentation with practical example.

The new declarationCommentMatchesPattern option is well documented with a practical use case (marking types that shouldn't be sorted via comments). The example code is clear and demonstrates the feature effectively.

Optional: Consider adding a brief distinction note.

While the current documentation is clear, you could optionally add a sentence explicitly distinguishing this from declarationMatchesPattern:

+- `declarationCommentMatchesPattern` — A regexp pattern to specify which comments above the type declaration should match. Unlike `declarationMatchesPattern` which matches the declaration name itself, this matches the comment content.
-  `declarationCommentMatchesPattern` — A regexp pattern to specify which comments above the type declaration should match.
📜 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 30183b1 and 576712c.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml, !pnpm-lock.yaml
📒 Files selected for processing (69)
  • 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)
  • eslint.config.ts (1 hunks)
  • index.ts (4 hunks)
  • package.json (4 hunks)
  • readme.md (1 hunks)
  • rules/sort-array-includes.ts (6 hunks)
  • rules/sort-array-includes/types.ts (0 hunks)
  • rules/sort-classes.ts (2 hunks)
  • rules/sort-decorators.ts (6 hunks)
  • rules/sort-decorators/types.ts (1 hunks)
  • rules/sort-enums.ts (6 hunks)
  • rules/sort-export-attributes.ts (1 hunks)
  • rules/sort-export-attributes/types.ts (1 hunks)
  • rules/sort-exports.ts (3 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 (7 hunks)
  • rules/sort-imports/types.ts (1 hunks)
  • rules/sort-interfaces.ts (2 hunks)
  • rules/sort-intersection-types.ts (2 hunks)
  • rules/sort-jsx-props.ts (6 hunks)
  • rules/sort-jsx-props/types.ts (4 hunks)
  • rules/sort-maps.ts (4 hunks)
  • rules/sort-modules.ts (3 hunks)
  • rules/sort-named-exports.ts (3 hunks)
  • rules/sort-named-exports/types.ts (1 hunks)
  • rules/sort-named-imports.ts (3 hunks)
  • rules/sort-named-imports/types.ts (1 hunks)
  • rules/sort-object-types.ts (10 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-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)
  • 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-exports/types.ts
  • rules/sort-array-includes/types.ts
  • docs/content/rules/sort-named-imports.mdx
  • docs/content/rules/sort-exports.mdx
  • docs/content/rules/sort-named-exports.mdx
  • test/rules/sort-exports.test.ts
🚧 Files skipped from review as they are similar to previous changes (21)
  • docs/content/rules/sort-import-attributes.mdx
  • rules/sort-intersection-types.ts
  • rules/sort-named-imports/types.ts
  • docs/content/rules/sort-intersection-types.mdx
  • rules/sort-imports/types.ts
  • rules/sort-enums.ts
  • rules/sort-export-attributes.ts
  • test/rules/sort-enums.test.ts
  • docs/content/rules/sort-sets.mdx
  • docs/content/rules/sort-imports.mdx
  • rules/sort-named-exports/types.ts
  • rules/sort-variable-declarations.ts
  • rules/sort-heritage-clauses/types.ts
  • rules/sort-objects/types.ts
  • rules/sort-classes.ts
  • readme.md
  • rules/sort-import-attributes/types.ts
  • eslint.config.ts
  • rules/sort-union-types.ts
  • rules/sort-export-attributes/types.ts
  • rules/sort-sets.ts
🧰 Additional context used
🧬 Code graph analysis (23)
rules/sort-object-types/get-custom-groups-compare-options.ts (1)
rules/sort-object-types/types.ts (1)
  • Options (28-106)
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-modules.ts (2)
rules/sort-array-includes.ts (1)
  • defaultOptions (60-74)
rules/sort-modules/types.ts (1)
  • SortModulesOptions (25-59)
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-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-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-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-named-imports.ts (5)
rules/sort-array-includes.ts (1)
  • defaultOptions (60-74)
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-switch-case.ts (1)
rules/sort-array-includes.ts (1)
  • defaultOptions (60-74)
rules/sort-interfaces.ts (3)
rules/sort-array-includes.ts (1)
  • defaultOptions (60-74)
rules/sort-object-types/types.ts (1)
  • Options (28-106)
rules/sort-object-types.ts (1)
  • sortObjectTypeElements (152-338)
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-jsx-props.ts (3)
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)
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-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-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-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-array-includes.ts (6)
types/sorting-node.ts (1)
  • SortingNode (18-102)
rules/sort-array-includes/types.ts (1)
  • Options (24-68)
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-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-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 (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-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-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)
test/rules/sort-imports.test.ts (1)
rules/sort-imports/types.ts (1)
  • Options (29-141)
test/rules/sort-object-types/get-custom-groups-compare-options.test.ts (2)
rules/sort-interfaces.ts (1)
  • Options (12-12)
rules/sort-object-types/types.ts (1)
  • Options (28-106)
🔇 Additional comments (29)
rules/sort-maps.ts (4)

25-25: LGTM!

The import change from getMatchingContextOptions to filterOptionsByAllNamesMatch improves code clarity with a more descriptive function name that better conveys the filtering behavior.


46-46: LGTM!

The type change from Required<Options[0]> to Required<Options[number]> adopts the idiomatic TypeScript pattern for referencing array element types, improving code consistency across the codebase.


81-88: LGTM!

The function call correctly adapts to the new filterOptionsByAllNamesMatch signature, passing nodeNames and contextOptions as an object parameter while preserving the original logic.


235-235: LGTM!

Adding defaultOptions to the rule metadata exposes the default configuration, improving rule introspection and documentation. The duplication with the root-level defaultOptions at line 239 is intentional per the migration objectives.

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

116-121: LGTM! Clean migration to groups-based API.

The error metadata has been correctly updated to use unexpectedNamedExportsGroupOrder with rightGroup and leftGroup fields for group-order violations. The migration from the deprecated groupKind option to the array-based groups format is properly implemented.

Also applies to: 167-167


1486-1491: LGTM! Consistent application across test sections.

The migration pattern is consistently applied in the natural sorting tests, maintaining the same structure and error metadata as the alphabetical tests.

Also applies to: 1537-1537


2856-2861: LGTM! Comprehensive test coverage across sorting types.

The migration is consistently applied across alphabetical, natural, and line-length sorting tests, ensuring the new groups-based API functions correctly with all sorting methods.

Also applies to: 2907-2907

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

287-287: LGTM! Type definition aligns with existing patterns.

The declarationCommentMatchesPattern type definition correctly follows the same pattern as other regex-based filter options in the codebase.


306-319: LGTM! Clear example of the new array-based API.

The example effectively demonstrates the migration to array-based customGroups, showing how to define custom groups with groupName and elementNamePattern properties. The RGB color sorting use case makes the feature easy to understand.

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

1-14: LGTM!

Import structure is clean with appropriate type-only imports and a single utility import for schema validation.


16-29: LGTM!

Options type correctly uses CustomGroupsOption<SingleCustomGroup> without the deprecated alternative, aligning with the v5 API changes. The decorator-specific options (sortOn*) are appropriate for controlling where decorator sorting applies.


31-33: LGTM!

The SingleCustomGroup interface appropriately defines the structure for custom decorator grouping based on element name patterns.


35-37: LGTM!

Type aliases are well-defined. SortDecoratorsSortingNode correctly specializes SortingNode for decorator nodes, and the internal Group type appropriately represents group identifiers.


39-41: LGTM!

The exported schema correctly maps elementNamePattern to the regex validation schema, enabling proper JSON schema validation for custom groups.

index.ts (2)

6-7: LGTM!

New rule imports for sort-import-attributes and sort-export-attributes follow the established import pattern and are correctly positioned alphabetically among other rule imports.


31-32: LGTM!

PluginConfig interface correctly extended with the new rule entries. Type annotations are appropriate and positioning follows the established order.

rules/sort-named-imports.ts (4)

54-68: LGTM!

The defaultOptions declaration correctly uses Required<Options[number]> to ensure all optional fields have default values. The default values are appropriate for the sort-named-imports rule.


165-177: LGTM!

The refactored sortNodesExcludingEslintDisabled function correctly delegates to sortNodesByGroups with proper options override via buildGetCustomGroupOverriddenOptionsFunction. This aligns with the group-based sorting approach adopted across the codebase.


179-192: LGTM!

The reportAllErrors invocation is correctly structured. The nodes are properly flattened, the sortNodesExcludingEslintDisabled function is passed for sorting within error reporting, and all message IDs are appropriately mapped.


229-229: LGTM!

Exposing defaultOptions in the rule metadata is good practice, allowing consumers to inspect the default configuration programmatically.

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

203-203: LGTM! Group identifier renamed consistently.

The group identifiers have been systematically updated from shorthand to shorthand-prop and multiline to multiline-prop throughout all test cases. This aligns with the PR objective to remove deprecated APIs and standardize naming.

Also applies to: 224-224, 259-259, 284-284, 1538-1538, 1559-1559, 1594-1594, 1619-1619, 2866-2866, 2887-2887, 2922-2922, 2947-2947


329-335: LGTM! Comprehensive migration to array-based customGroups API.

The test file demonstrates a thorough migration from an object-based customGroups API to an array-based API. The new structure provides:

  1. Better support for multiple custom groups with the same matching criteria
  2. Cleaner syntax with explicit groupName properties
  3. Support for advanced features like elementNamePattern, elementValuePattern, modifiers, and anyOf
  4. Per-group configuration overrides (type, order, fallbackSort)

The migration is systematic and covers all test scenarios comprehensively.

Also applies to: 867-872, 933-942, 976-997, 1079-1092, 1188-1199, 1248-1267, 1664-1670, 2202-2207, 2268-2277, 2311-2332, 2414-2427, 2999-3004, 3537-3542, 3603-3612, 3646-3667, 3749-3762

rules/sort-imports.ts (7)

68-70: LGTM! Type refinement aligns with array-based Options.

The type change from Options to Options[number] correctly reflects that Options is now an array type (as defined at line 28 of rules/sort-imports/types.ts). Using indexed access type [number] extracts the element type of the array.


109-109: LGTM! Simplified validation call.

Passing the full options object directly to validateGeneratedGroupsConfiguration is cleaner than the previous approach of wrapping/extracting specific properties. This aligns with the removal of deprecated API patterns.


115-115: LGTM! Cleaner tsconfig configuration structure.

The migration from options.tsconfigRootDir to options.tsconfig?.rootDir provides a better-organized API by grouping TypeScript configuration under a single tsconfig object. This is a breaking change but aligns with the PR objectives to remove deprecated APIs.


313-313: LGTM! Consistent removal of options wrapping.

Passing the full options object directly to getCustomGroupOverriddenOptions and reportAllErrors is more straightforward and eliminates unnecessary wrapping layers. This simplification is consistent with the changes at line 109.

Also applies to: 368-368


425-427: LGTM! Schema migration to array-based customGroups.

The use of buildCustomGroupsArrayJsonSchema({ singleCustomGroupJsonSchema }) aligns with the comprehensive migration to an array-based customGroups API seen throughout the codebase. This provides better JSON schema validation for the new API structure.


533-564: LGTM! Clean helper function for group computation.

The new computeGroupExceptUnknown function provides a cleaner abstraction by:

  1. Encapsulating the group computation logic
  2. Returning null when the computed group is 'unknown', allowing the caller to provide a fallback
  3. Accepting a properly typed subset of options (omitting maxLineLength and tsconfig which aren't needed for group computation)

This improves code organization and makes the intent clearer at the call site (lines 223-228).


453-453: No action needed: defaultOptions duplication is intentional and consistent All rules (including sort-imports.ts) declare defaultOptions in meta and at the root; this matches the project pattern.

Comment on lines 269 to 286
groups: ['r', 'g', 'b'], // Sort tag with colors keys 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

Fix the RGB regex example.

'^r|g|b$' is parsed as (^r) or g or (b$), so it matches many names that do not start/end with the intended letters. Please wrap the alternatives in a single, anchored group.

-        allNamesMatchPattern: '^r|g|b$',
+        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 tag with colors keys 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 tag with colors keys 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-jsx-props.mdx around lines 269 to 286, the regex
'^r|g|b$' is incorrectly anchored and thus matches unintended names; replace it
with a single anchored alternation such as '^(r|g|b)$' or '^(?:r|g|b)$' so the
pattern matches only names that are exactly "r", "g", or "b".

Comment on lines +75 to +98
export let 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,
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion | 🟠 Major

Use const for the rules export.

The rules object is part of the public API and should be immutable to prevent accidental modification.

Apply this diff:

-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,
}
📝 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
export let 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,
}
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,
}
🤖 Prompt for AI Agents
In index.ts around lines 75 to 98, the export uses "let rules" which allows
reassignment; change it to "export const rules" so the rules object is immutable
as part of the public API, and scan the repo for any reassignment or mutation
sites (remove or update them) to ensure no code expects rules to be re-bound or
reassigned.

Comment on lines 43 to 55
let { fallbackSort, customGroups, sortBy, groups } = options
let fallbackSortBy = fallbackSort.sortBy
if (Array.isArray(customGroups)) {
let group = groups[groupIndex]
let customGroup =
typeof group === 'string'
? customGroups.find(currentGroup => group === currentGroup.groupName)
: null
let group = groups[groupIndex]
let customGroup =
typeof group === 'string'
? customGroups.find(currentGroup => group === currentGroup.groupName)
: null

if (customGroup) {
fallbackSortBy = customGroup.fallbackSort?.sortBy ?? fallbackSortBy
if ('sortBy' in customGroup && customGroup.sortBy) {
;({ sortBy } = customGroup)
}
if (customGroup) {
fallbackSortBy = customGroup.fallbackSort?.sortBy ?? fallbackSortBy
if ('sortBy' in customGroup && customGroup.sortBy) {
;({ sortBy } = customGroup)
}
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

Restore custom overrides for grouped entries.

After removing the old object-map path we now only look up overrides when group is a string. For group blocks like ['index-signature', 'member'] (or any array entry produced by GroupsOptions) we never resolve the corresponding customGroup, so per-group sortBy/fallbackSort overrides stop applying. This breaks existing configurations that combine groups.

Please collect all group names (strings inside arrays) before searching the customGroups list so the override still kicks in for grouped entries.

-  let group = groups[groupIndex]
-  let customGroup =
-    typeof group === 'string'
-      ? customGroups.find(currentGroup => group === currentGroup.groupName)
-      : null
+  let group = groups[groupIndex]
+  let groupNames =
+    typeof group === 'string'
+      ? [group]
+      : Array.isArray(group)
+        ? group
+        : []
+  let customGroup =
+    groupNames
+      .map(name =>
+        customGroups.find(currentGroup => currentGroup.groupName === name),
+      )
+      .find(
+        (matchedGroup): matchedGroup is (typeof customGroups)[number] =>
+          Boolean(matchedGroup),
+      ) ?? null
📝 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 { fallbackSort, customGroups, sortBy, groups } = options
let fallbackSortBy = fallbackSort.sortBy
if (Array.isArray(customGroups)) {
let group = groups[groupIndex]
let customGroup =
typeof group === 'string'
? customGroups.find(currentGroup => group === currentGroup.groupName)
: null
let group = groups[groupIndex]
let customGroup =
typeof group === 'string'
? customGroups.find(currentGroup => group === currentGroup.groupName)
: null
if (customGroup) {
fallbackSortBy = customGroup.fallbackSort?.sortBy ?? fallbackSortBy
if ('sortBy' in customGroup && customGroup.sortBy) {
;({ sortBy } = customGroup)
}
if (customGroup) {
fallbackSortBy = customGroup.fallbackSort?.sortBy ?? fallbackSortBy
if ('sortBy' in customGroup && customGroup.sortBy) {
;({ sortBy } = customGroup)
}
let { fallbackSort, customGroups, sortBy, groups } = options
let fallbackSortBy = fallbackSort.sortBy
let group = groups[groupIndex]
let groupNames =
typeof group === 'string'
? [group]
: Array.isArray(group)
? group
: []
let customGroup =
groupNames
.map(name =>
customGroups.find(currentGroup => currentGroup.groupName === name),
)
.find(
(matchedGroup): matchedGroup is (typeof customGroups)[number] =>
Boolean(matchedGroup),
) ?? null
if (customGroup) {
fallbackSortBy = customGroup.fallbackSort?.sortBy ?? fallbackSortBy
if ('sortBy' in customGroup && customGroup.sortBy) {
;({ sortBy } = customGroup)
}
🤖 Prompt for AI Agents
In rules/sort-object-types/get-custom-groups-compare-options.ts around lines 43
to 55, the current logic only finds a customGroup when group is a string and
therefore misses overrides when group is an array (e.g.,
['index-signature','member']). Update the lookup so if group is an array you
first collect all string names from that array (e.g., filter/map to strings),
then search customGroups for any entry whose groupName matches any of those
names; use the first match as customGroup, then apply its fallbackSort.sortBy
and sortBy overrides exactly as you do now for string groups so per-group
overrides still take effect for grouped entries.

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
2 participants