-
Notifications
You must be signed in to change notification settings - Fork 54
release v5.0.0 #569
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
release v5.0.0 #569
Conversation
|
Note Reviews pausedUse the following commands to manage reviews:
📝 WalkthroughSummary by CodeRabbitRelease Notes
✏️ Tip: You can customize this high-level summary in your review settings. WalkthroughProject-wide migration to ESM and Node ≥20; replaced object-mapped Changes
Sequence Diagram(s)sequenceDiagram
autonumber
participant ESLint
participant Rule
participant Matcher as CustomGroupMatcher
participant Partitioner
participant Sorter
participant Reporter
ESLint->>Rule: visit AST node and collect attributes/members
Rule->>Matcher: match item against array-based customGroups
Matcher-->>Rule: returns groupName or 'unknown'
Rule->>Partitioner: decide partitions (partitionByNewLine / partitionByComment)
Partitioner-->>Rule: partitions[]
loop per partition
Rule->>Sorter: sort partition with per-group overrides (type/order/newlinesInside)
Sorter-->>Rule: sorted nodes and spacing info
Rule->>Reporter: emit diagnostics (group-order, element-order, spacing) with leftGroup/rightGroup context
end
Estimated code review effort🎯 5 (Critical) | ⏱️ ~120+ minutes Areas needing extra attention:
Possibly related PRs
Suggested reviewers
Pre-merge checks❌ Failed checks (2 warnings, 1 inconclusive)
✅ Passed checks (2 passed)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this 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 pathsUsing 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
📒 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 acknowledgedSwitching "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+ — goodThis 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+ policyThe
peerDependenciesentry 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 — goodformats: ['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 generationLooks 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 fordtsPluginESLint flags
dts(...)as ananycall because TypeScript cannot resolve the default import’s types. Please verify that your roottsconfig.json(which extends@azat-io/typescript-config) enables:•
esModuleInterop: trueorallowSyntheticDefaultImports: true
• A moduleResolution mode supporting ES modules (e.g."NodeNext"or"Bundler")If those aren’t set, add them under
compilerOptionsin your roottsconfig.json.
Alternatively, you can:
Create a typed alias in
vite.config.tsbefore callingdts:import type { Plugin } from 'vite' import dts, { type Options as DtsOptions } from 'vite-plugin-dts' const dtsPlugin: (options?: DtsOptions) => Plugin = dts // … plugins: [ dtsPlugin({ /* … */ }) ]Or, as a last resort, disable the rule for that line:
// eslint-disable-next-line @typescript-eslint/no-unsafe-call dts({ /* … */ })Locations to verify:
- vite.config.ts:27
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #569 +/- ##
==========================================
Coverage 100.00% 100.00%
==========================================
Files 101 111 +10
Lines 8565 9011 +446
Branches 1688 1747 +59
==========================================
+ Hits 8565 9011 +446 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
There was a problem hiding this 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 includeThe 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 removingThe 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 suppressStatic 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.
⛔ Files ignored due to path filters (1)
pnpm-lock.yamlis 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 goodformats: ['es'] aligns with the ESM-only migration and ESLint 9.
35-35: Good addition: copyDtsFilescopyDtsFiles: true helps keep declaration files in sync alongside preserveModules.
| path.resolve(import.meta.dirname, 'index.ts'), | ||
| path.resolve(import.meta.dirname, 'utils', 'alphabet.ts'), | ||
| ], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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).
There was a problem hiding this 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 shimYour engines field allows Node 20, but
import.meta.dirnameis only available in Node 22+. Replace it with an ESM-safe__dirnameshim 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 factoryESLint 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 thetestblock is typed and discoverableImporting
defineConfigfromvitest/configensures thetestproperty 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 outputThis 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.
⛔ Files ignored due to path filters (1)
pnpm-lock.yamlis 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 — LGTMThe switch to formats: ['es'] with preserveModules aligns with the ESM-only objective. File naming is consistent and explicit.
There was a problem hiding this 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 everycustomGroups: { /* 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:
- Prefer proper typing
// package.json (devDependencies) "@types/dedent": "^1.0.3"
- 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
📒 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 thatmissedSpacingBetweenDecorators,extraSpacingBetweenDecorators,unexpectedDecoratorsGroupOrder, andunexpectedDecoratorsOrderare referenced throughouttest/rules/sort-decorators.test.ts.
169-176: AccessorProperty is supported by current parser version
@typescript-eslint/parser v8.39.0 includesAST_NODE_TYPES.AccessorProperty(introduced in v7.16.0), so this listener will fire as intended. (newreleases.io)
| 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 }[] | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
| 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.
There was a problem hiding this 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 newlinesBetweenCode/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 docsdocs/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.tspackage.json (1)
20-23: Alphabet types path does not match emitted structure.Exports map
"./alphabet".typesto./dist/alphabet.d.tswhile JS points to./dist/utils/alphabet.js. With preserveModules and current includes, the d.ts will land underdist/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.tsat 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 goodMirrors the alphabetical suite updates.
Also applies to: 1769-1775, 1779-1784
3283-3285: Same change here — looks goodConsistent 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 aboveGroup-order assertions and config look consistent for the natural sort suite.
Also applies to: 1911-1912
3371-3377: Same change pattern as aboveGroup-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 aboveConfig and expectations look consistent for the natural sort suite.
Also applies to: 1537-1538
2856-2862: Same change pattern as aboveConfig 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
anyOfwithselector: '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 testSwitch to real spread usage to cover the
spreadselector.- 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 testUpdate to actual spread to validate
anyOfwithselector: '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: hoistgetOptionsByGroupIndexto avoid recreating per call.
reportAllErrorscallssortNodesExcludingEslintDisabledtwice; 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 mapThis 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 pathTests 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 methodrules/sort-heritage-clauses.ts (3)
46-59: Defaults align with new options; minor nitSetting 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 wiredreportAllErrors 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 importsThe 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 idTests 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
⛔ Files ignored due to path filters (1)
pnpm-lock.yamlis 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: LGTMAdopting
groups: ['spread']matches the new API and keeps the test intent clear.
247-253: Group-aware error assertions: LGTMSwitch to
unexpectedSetsGroupOrderwith{ 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 optionalreportAllErrors 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 stalegroupKindusages found.
DroppinggroupKindfrom 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 migrationUnioned 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 testsrg 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 combosThese 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 pipelineThe 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 — keepimport { 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
nameif 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.
There was a problem hiding this 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 shapeUpdate 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
AllowedModifiersPerSelectorincludes amultilineselector that doesn’t exist.- Declares
index-signature: neverbut 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 modifiersIndex signatures don’t accept
optional/required/multilinemodifiers. 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
newlinesBetweenValueGettersoreportAllErrorscan evaluate thenewlinesBetweenoption 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
reportAllErrorscall is missing thenewlinesBetweenValueGetterparameter, which prevents detection of missed/extra blank-line errors whenoptions.newlinesBetweenis 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: Makeflagsoptional to match RegexOption
flagsshould 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 constantsUse
constfor 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 statementPR drops ESLint v8; revise to v9+ to avoid confusion.
-- Compatible with ESLint v8.45.0 or greater +- Compatible with ESLint v9.0.0 or greaterindex.ts (2)
71-71: Use const for immutable plugin nameMinor tidy-up.
-let pluginName = 'perfectionist' +const pluginName = 'perfectionist'
73-101: Avoid double assertion; use satisfies for stronger typingThis keeps type safety without
unknowncasts.-let plugin = { +const plugin = { rules: { // ... }, meta: { version: packageVersion, name: packageName, }, -} as unknown as ESLint.Plugin +} satisfies ESLint.Plugindocs/content/rules/sort-import-attributes.mdx (1)
33-39: Fix line-length preview: show actual length-based orderFor 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
Grouptype 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
📒 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 APIExample correctly shows
groupName+elementNamePattern.
398-416: Good: clear example for declarationCommentMatchesPatternDocs and example are consistent.
752-754: Broken test link pathTests 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 goodOption shape matches RegexOption usage.
58-65: Per‑group fallbackSort extension is reasonableTyping extension for
fallbackSortwithsortByis consistent with global option.
235-238: PropertyGroup introduction is consistentMatches the other selector groups’ pattern.
380-389: Sorting node shape LGTM
valuefor type-annotation text is appropriate; nullable is correct.docs/public/llms.txt (2)
17-26: Good: link hygiene to canonical docsUpdated URLs look correct.
30-50: Good: new rule listed
sort-import-attributesentry added consistently with others.index.ts (1)
6-6: Rule wiring for sort-import-attributes is correctImport, typing, and rules map entry are all present.
Please confirm the file exists at
rules/sort-import-attributes.tsand is exported as default.Also applies to: 31-31, 77-77
docs/content/rules/sort-import-attributes.mdx (2)
146-157: newlinesBetween semantics clearly describedMatches rule behavior; no changes needed.
268-275: Version and resources look rightIntro 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
SingleCustomGroupinterface 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-multilinetooptional-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
elementNamePatternandgroupNamefields. The multi-configuration approach withallNamesMatchPatternfiltering is well-tested.
2442-2497: Good addition: Test coverage for declaration comment matching.The new test validates the
declarationCommentMatchesPatternfilter, 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
MessageIdtype 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
getAttributeNamefunction 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
customGroupsto array-basedGroupDefinitionobjects is implemented correctly. The new structure withelementNamePatternandgroupNameproperties 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-propandmultiline-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: {}tocustomGroups: []correctly reflects the migration to array-based custom groups. The typing update toRequired<Options[number]>is also appropriate.
94-95: LGTM! JSON schema supports declarationCommentMatchesPattern.The addition of
declarationCommentMatchesPatternto the schema enables comment-based configuration filtering.
98-101: LGTM! CustomGroups schema migrated to array builder.The migration to
buildCustomGroupsArrayJsonSchemawith 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
computeMatchedContextOptionshelper 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
computeMatchedContextOptionsfunction properly implements the filtering pipeline:
- Filters by all names matching pattern
- Filters by declaration comment matching pattern
- Checks declaration name pattern
This enables flexible configuration selection based on multiple criteria.
There was a problem hiding this 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 formThe 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 validUse 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 testsReplace 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]: stringtest/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 specificityThe 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
reportAllErrorsfunction signature in the relevant code snippets, the call is missing thenewlinesBetweenValueGetterparameter which is required for spacing diagnostics to work correctly.Looking at the
utils/report-all-errors.tscode, the function expects anewlinesBetweenValueGetterparameter. 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 allNamesMatchPatternUse 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 torules/sort-jsx-props/types.ts (1)
146-153: Prefer const over let for immutable tablesThese 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 defaultOptionsAvoid 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 forattributesThe current check for
node.attributesmay not be sufficient. Consider checking ifattributesexists 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 commentThe 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 logicThis pattern of creating
createSortNodesExcludingEslintDisabledis identical to the one insort-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 MessageIdThe 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 modesTest 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 wrapperThe 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 utilitiesThe
removeLiteralValuefunction and parser wrapping logic is duplicated fromsort-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
⛔ Files ignored due to path filters (1)
pnpm-lock.yamlis 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 LGTMcustomGroups 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 goodMatches repo-wide changes (array customGroups, explicit order/groups).
48-50: Passing parentNode and context — correctThe 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 — goodExamples 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 effectivelyThe
getAttributeNamefunction 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 integratedThe new
sort-import-attributesandsort-export-attributesrules 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 configuredThe 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 typeonly, 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 coverageThe 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 includedGood 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
Identifierand 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.
There was a problem hiding this 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 }insidegroups, 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 docsrules/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?: stringfor 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.
Selectorno longer includes'multiline', yetAllowedModifiersPerSelectorand 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
constfor 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
readonlyarrays orObject.freeze(...).
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 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
groupstype 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‑enddeclarationCommentMatchesPattern (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
MultilineGroupremoved, audit tests/docs for tokens likemultiline-propertyetc., and ensure schema forgroupscan’t accept them.
100-104: Confirm intent: remove legacyignorePatternor keep and documentDocs and commits mark
ignorePatternas 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
ignorePatternfrom 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.
There was a problem hiding this 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 asand take advantage ofsatisfies. Also, reference the localrulesmap 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
📒 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.
There was a problem hiding this 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 includerules/
Replace the test link so it points totest/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
newlinesBetweenValueGettertoreportAllErrorsso 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 includerules/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 docsThe 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” methodUse the correct method name in the short description.
-shortDescription: Enforce sorted arrays before include method +shortDescription: Enforce sorted arrays before includes methodrules/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 testsAlphabet.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 attributesBe 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 runSame 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 testsCache 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-checkedPrefer 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 assertionUse 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 directlyNo 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 APITests 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 APIDocs 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 examplesThe 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 objectMinor: 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
⛔ Files ignored due to path filters (1)
pnpm-lock.yamlis 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)
| let nodes = formattedMembers.flat() | ||
| reportAllErrors<MessageIds>({ | ||
| sortNodesExcludingEslintDisabled, | ||
| availableMessageIds, | ||
| sourceCode, | ||
| options, | ||
| context, | ||
| nodes, | ||
| }) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
| 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.
| it('sorts import attributes', async () => { | ||
| await valid({ | ||
| code: dedent` | ||
| export { data } from 'module' with { a: 'a', b: 'b', c: 'c' } | ||
| `, | ||
| options: [options], | ||
| }) | ||
|
|
||
| await invalid({ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
| 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.
There was a problem hiding this 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
📒 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 ingetObjectParent.When the object literal sits under a
Property, we still fabricate{ type: 'VariableDeclarator' }. As a resultdeclarationMatchesPattern/declarationCommentMatchesPatterntreat 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, + } }
There was a problem hiding this 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 missingThis refactor drops the
newlinesBetweenValueGetteryou previously had wired intoreportAllErrors, so the rule no longer reports newline/spacing violations. Restore it (and importgetLinesBetween) 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
TSTypeLiteralnodes (type aliases). A past review comment suggested adding aTSInterfaceBodyvisitor to also sort interface members, and was marked as addressed. However, noTSInterfaceBodyvisitor 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.ImportClausebut sorting nodes are built fromTSESTree.ImportSpecifier(seerules/sort-named-imports.ts:136wherenode: specifieris assigned and specifier is filtered bytype === '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.typeshould be a specific union (notstring), andnewlinesInsideshould accept'always' | 'never' | numberto 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.typeshould be a specific union, andnewlinesInsideshould 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
flagsshould be optional in theRegExpPatterntype 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 thetypeunion, use a specific union forfallbackSort.type(notstring), and expandnewlinesInsideto 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'intype, use a specific union forfallbackSort.type, and expandnewlinesInside.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
CustomGroupAnyOfDefinitioninterface includes aselector?field in theanyOfitems, 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 missingnewlinesBetweenValueGetter.We now emit spacing message IDs but the
reportAllErrorscall still omitsnewlinesBetweenValueGetter. Without it, spacing violations are never detected, so the new messages will never fire. Please wire it back in and importgetLinesBetween.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
reportAllErrorscan’t emit newline/spacing violations without anewlinesBetweenValueGetter. 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: MissingnewlinesBetweenValueGetterinreportAllErrorscall.The
reportAllErrorscall is missing thenewlinesBetweenValueGetterparameter, which prevents spacing diagnostics (missedSpacingBetweenImportAttributesandextraSpacingBetweenImportAttributes) 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,reportAllErrorscannot compute missed/extra blank-line errors whenoptions.newlinesBetweenis 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:
- Renaming to "sorts enum members with string number keys" or "sorts enum members with numeric string keys"
- Or if the intent is to test actual numeric keys, reverting to numeric keys:
1,12,2,8The 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 leakageAdd 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
⛔ Files ignored due to path filters (1)
pnpm-lock.yamlis 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)
| 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, | ||
| }) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
| 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.
There was a problem hiding this 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: 0for 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
reportAllErrorscall is still missing thenewlinesBetweenValueGetterparameter, 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 calculatorSpacing/newline diagnostics never fire because
reportAllErrorsreceives nonewlinesBetweenValueGetter. Provide it (and importgetLinesBetween) so the rule can emit the promised spacing errors.Apply this diff to import
getLinesBetweenat 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
newlinesBetweenValueGetterin thereportAllErrorscall: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 passingisNodeIgnoredtosortNodesByGroupsto 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
newlinesBetweenValueGetterparameter 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-includesrules/sort-objects.ts (2)
553-594: Address type safety: don't conflate Property with VariableDeclarator.The return type declares
type: 'VariableDeclarator'but thenodefield can be eitherTSESTree.VariableDeclarator | TSESTree.Property(line 563). This makesdeclarationMatchesPatternmatching fire incorrectly for nested object literals, as noted in a previous review.Separate the union so
Propertyparents 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
computeMatchedContextOptionsto checkobjectParent.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
newlinesBetweenValueGettersoreportAllErrorscan evaluatenewlinesBetweenfor 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
newlinesBetweenValueGettersoreportAllErrorscan 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
newlinesBetweenValueGettersoreportAllErrorscan compute missed/extra blank-line errors whenoptions.newlinesBetweenis 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
TSInterfaceBodyvisitor that callssortObjectTypeElementswithparentNodeset whennode.parent.type === 'TSInterfaceDeclaration'andelements: 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 observationThe 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
⛔ Files ignored due to path filters (1)
pnpm-lock.yamlis 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 ofdefaultOptionsin both themetaobject and at the top level aligns with the established pattern across other rules and thecreateEslintRulehelper signature.rules/sort-intersection-types.ts (2)
20-20: LGTM: Typing refinement aligns with array-based options standard.The change from
Options[0]toOptions[number]correctly represents thatdefaultOptionsshould match any element of theOptionsarray 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
defaultOptionsto 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
MessageIdtype 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
computeGrouputility- 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: trueis suitable for a new sorting rule- Default options are properly declared
204-213: LGTM!The
getAttributeNamehelper correctly handles bothIdentifierandLiteralkey 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
getMatchingContextOptionstofilterOptionsByAllNamesMatchis 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]>toRequired<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
filterOptionsByAllNamesMatchproperly provides the required parameters (nodeNamesandcontextOptions). ThenodeNamescomputation 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
defaultOptionsto the rule'smetaobject 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
configsproperty 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]>toRequired<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
defaultOptionsin the rule's metadata is consistent with the pattern applied across multiple rules in this PR.
55-67: LGTM: Handler signature updated correctly.The
TSInterfaceDeclarationhandler now properly forwardsparentNode,elements, andcontexttosortObjectTypeElements, matching the expected function signature shown inrules/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]>toRequired<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
defaultOptionsin 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]>toRequired<Options[number]>is consistent with the PR-wide migration.
225-225: LGTM: defaultOptions exposed in meta.Exposing
defaultOptionsin 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
defaultOptionsremoves the deprecatedgroupKindfield and introducesgroups: []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
sortNodesExcludingEslintDisabledfunction correctly delegates tosortNodesByGroupswith per-group options viabuildGetCustomGroupOverriddenOptionsFunction. Centralized error reporting viareportAllErrorsis consistent with the pattern used in other rules (e.g.,sort-named-imports,sort-exports).
232-232: LGTM: defaultOptions exposed in meta.Exposing
defaultOptionsin 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
filterOptionsByAllNamesMatchimport 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
groupKindfield to a simple type alias aligns with the PR-wide removal of the deprecatedgroupKindproperty.
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
defaultOptionsin 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
allNamesMatchPatternconfiguration, 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
groupKindproperty.rules/sort-named-imports.ts (3)
54-68: LGTM: defaultOptions migrated to groups-based model.The updated
defaultOptionsremoves the deprecatedgroupKindfield and introducesgroups: []as the default, aligning with the PR-wide migration.
165-192: LGTM: Sorting flow refactored to use groups-based model.The new
sortNodesExcludingEslintDisabledfunction correctly delegates tosortNodesByGroups. This pattern is consistent with other rules in the PR. TheSortNamedImportsSortingNodetype issue noted in a previous review has been addressed.
229-229: LGTM: defaultOptions exposed in meta.Exposing
defaultOptionsin 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
groupKindfield to a simple type alias aligns with the PR-wide removal of the deprecatedgroupKindproperty.
54-67: LGTM: defaultOptions migrated to groups-based model.The updated
defaultOptionsremoves the deprecatedgroupKindfield and introduces array-based grouping, aligning with the PR-wide migration.
151-179: LGTM: Sorting flow refactored to use groups-based model.The new
sortNodesExcludingEslintDisabledfunction correctly delegates tosortNodesByGroupswith per-group options. Centralized error reporting viareportAllErrorsis consistent with the pattern used in other rules.
220-220: LGTM: defaultOptions exposed in meta.Exposing
defaultOptionsin 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
filterOptionsByDeclarationCommentMatchesandfilterOptionsByAllNamesMatchimports support the newdeclarationCommentMatchesPatternandallNamesMatchPatternconfiguration options inuseConfigurationIf.Also applies to: 37-37
66-84: LGTM: defaultOptions migrated to groups-based model.The updated
defaultOptionsintroduces array-basedcustomGroupsand addsuseConfigurationIf: {}, aligning with the PR-wide migration.
98-102: LGTM: Context matching refactored to use computeMatchedContextOptions.The new
computeMatchedContextOptionsfunction centralizes context option filtering. The function implementation will be reviewed separately.
117-119: LGTM: Simplified control flow for objectDeclarations check.The
else ifstructure is clearer and maintains the same logic.
425-442: LGTM: Schema updated for new configuration options.The schema correctly exposes new
useConfigurationIfproperties (declarationCommentMatchesPattern,declarationMatchesPattern) and uses array-basedcustomGroupsschema.
467-467: LGTM: defaultOptions exposed in meta.Exposing
defaultOptionsin 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
computeMatchedContextOptionsfunction correctly:
- Filters by
allNamesMatchPatternanddeclarationCommentMatchesPattern- Guards
callingFunctionNamePatternmatching withobjectParent.type === 'CallExpression'check (lines 521)- Guards
declarationMatchesPatternmatching withobjectParent.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
VariableDeclaratorandPropertyparent types, extracting the appropriate identifier name from each.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 3
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (6)
docs/content/rules/sort-object-types.mdx (2)
721-721: Remove deprecatedignorePatternfrom defaults in Usage examples.Docs mark
ignorePatternas deprecated, but the Flat/Legacy config blocks still include it. Drop it to avoid suggesting removed APIs.- ignorePattern: [],Also applies to: 754-754
189-191: Minor wording“Use object types keys” → “Use object type keys.”
docs/content/rules/sort-intersection-types.mdx (1)
401-401: Minor grammarUse “A type member …” instead of “An type member …”.
Also applies to: 419-419
docs/content/rules/sort-modules.mdx (1)
276-281: Terminology: “class” → “module members”This rule sorts module members; adjust the description in
partitionByNewLine.- When `true`, the rule will not sort the members of a class if there is an empty line between them. + When `true`, the rule will not sort module members if there is an empty line between them.docs/content/rules/sort-sets.mdx (1)
296-302: Fix wording: this rule targets Set elements, not Array elements.Minor clarity tweak.
-- `literal` — Array elements that are not spread values. - - `spread` — Array elements that are spread values. +- `literal` — Set elements that are not spread values. +- `spread` — Set elements that are spread values.docs/content/rules/sort-objects.mdx (1)
627-631: customGroups type shows old API; update to array-based definitions.This contradicts the migration notice just above. Switch to the new array signature for consistency.
-<sub> - type: `{ [groupName: string]: string | string[] }` -</sub> +<sub> + type: `Array<CustomGroupDefinition | CustomGroupAnyOfDefinition>` +</sub>
♻️ Duplicate comments (6)
docs/content/rules/sort-heritage-clauses.mdx (1)
291-298: Include'custom'intypeunion and alignnewlinesInsidetyping (consistency).Add
'custom'to thetypeunion and considernewlinesInside?: 'always' | 'never' | numberto match other docs/interfaces.interface CustomGroupDefinition { groupName: string - type?: 'alphabetical' | 'natural' | 'line-length' | 'unsorted' + type?: 'alphabetical' | 'natural' | 'line-length' | 'custom' | 'unsorted' order?: 'asc' | 'desc' fallbackSort?: { type: string; order?: 'asc' | 'desc' } - newlinesInside?: number + newlinesInside?: 'always' | 'never' | number elementNamePattern?: string | string[] | { pattern: string; flags?: string } | { pattern: string; flags?: string }[] } interface CustomGroupAnyOfDefinition { groupName: string - type?: 'alphabetical' | 'natural' | 'line-length' | 'unsorted' + type?: 'alphabetical' | 'natural' | 'line-length' | 'custom' | 'unsorted' order?: 'asc' | 'desc' fallbackSort?: { type: string; order?: 'asc' | 'desc' } - newlinesInside?: number + newlinesInside?: 'always' | 'never' | number anyOf: Array<{ selector?: string elementNamePattern?: string | string[] | { pattern: string; flags?: string } | { pattern: string; flags?: string }[] }> }Also applies to: 306-317
docs/content/rules/sort-modules.mdx (2)
517-522: Fix trailing dot in example (invalid TS/JSON).Remove the dot after
'Input'inelementNamePattern.- elementNamePattern: 'Input'. + elementNamePattern: 'Input' … - elementNamePattern: 'Input'. + elementNamePattern: 'Input'
685-686: Update test link pathTests live under
test/rules/….-- [Test source](https://github.com/azat-io/eslint-plugin-perfectionist/blob/main/test/sort-modules.test.ts) +- [Test source](https://github.com/azat-io/eslint-plugin-perfectionist/blob/main/test/rules/sort-modules.test.ts)docs/content/rules/sort-enums.mdx (1)
173-180: sortByValue default and enum values — LGTM.Clear explanation of 'always' | 'never' | 'ifNumericEnum'.
docs/content/rules/sort-decorators.mdx (1)
368-407: AlignCustomGroupDefinition/CustomGroupAnyOfDefinitiontypings with runtimeThe examples still show:
fallbackSort?: { type: string; order?: 'asc' | 'desc' }newlinesInside?: numberwhile the rest of the rule (and prior review context) indicate a more precise shape and additional literal values for
newlinesInside. To avoid misleading consumers, please update both interfaces to mirror the runtime/types module, e.g.:interface CustomGroupDefinition { groupName: string - type?: 'alphabetical' | 'natural' | 'line-length' | 'unsorted' + type?: 'alphabetical' | 'natural' | 'line-length' | 'custom' | 'unsorted' order?: 'asc' | 'desc' - fallbackSort?: { type: string; order?: 'asc' | 'desc' } - newlinesInside?: number + fallbackSort?: { + type: 'alphabetical' | 'natural' | 'line-length' | 'custom' | 'unsorted' + order?: 'asc' | 'desc' + } + newlinesInside?: 'always' | 'never' | number + selector?: string elementNamePattern?: string | string[] | { pattern: string; flags?: string } | { pattern: string; flags?: string }[] }and similarly for
CustomGroupAnyOfDefinition’sfallbackSortandnewlinesInside. Also consider expanding thenewlinesInsidebullet point to mention the allowed string literals explicitly.Based on past review comments
docs/content/rules/sort-jsx-props.mdx (1)
284-286: Fix the RGB regex pattern (duplicate of prior feedback).The regex pattern
'^r|g|b$'inallNamesMatchPatternis incorrectly anchored. It parses as(^r)orgor(b$), matching unintended names like "something_g_anything" in addition to the intended "r", "g", "b". This was flagged in a prior review and remains unfixed.Apply this fix:
useConfigurationIf: { - allNamesMatchPattern: '^r|g|b$', + allNamesMatchPattern: '^(?:r|g|b)$', },
🧹 Nitpick comments (29)
docs/content/rules/sort-classes.mdx (1)
738-783: Complex customGroups example may benefit from additional guidance.The extended example at lines 738–783 demonstrates advanced features (multiple custom groups, selector/modifier filters, anyOf patterns) but is quite dense. While comprehensive, it could be enhanced with:
- A simpler introductory example (e.g., single custom group) before this complex one.
- Step-by-step explanations within the code comments to guide users through the logic.
The example is correct and covers important patterns, but readability could be improved for users unfamiliar with the customGroups API.
Consider breaking this into a simpler introductory example followed by the current advanced example, or add inline comments explaining the matching logic (e.g., "This group matches constructor() to prevent sorting" at line 755).
test/rules/sort-classes.test.ts (5)
4129-4178: Clarify test title or remove unused boundary in groups.The test name says: “enforces no newline … when 'newlinesBetween: 0' exists between all groups”, but the groups array also contains an unused
{ newlinesBetween: 1 }boundary later in the list. Since only 'a' and 'b' are present in the code, it’s harmless but confusing. Either:
- rename the test to “…between relevant groups”, or
- drop the trailing
{ newlinesBetween: 1 }(and 'c') from groups to match the title exactly.Also applies to: 8780-8829, 13363-13412
3894-3946: Normalize fixture indentation in newline‑removal tests.The inputs/outputs mix inconsistent leading spaces (e.g., lines for y/z). This can make tests brittle against formatting tweaks. Consider aligning indentation (or adding a comment that spacing is intentional) to keep focus on newline behavior.
Also applies to: 8544-8596, 13135-13180
3949-3952: Add “2” case to overload‑signature spacing matrix.You already test newlinesBetween = 0, 1, and 'ignore'. Add a '2' case to ensure overload signatures still collapse adjacent lines even when the global/group setting prefers extra blank lines.
Please confirm that overloads must always be contiguous regardless of newlinesBetween (including 2). If not, we can drop this suggestion.
Also applies to: 8599-8601, 13183-13185
14691-14794: newlinesInside coverage is good; consider edge values if supported.Nice addition of newlinesInside = 0 and 1. If the option also supports 2 (or 'ignore'), add a small matrix similar to overload tests; otherwise, a brief comment noting supported values would help readers.
Confirm the allowed domain for
newlinesInside(0/1 only vs. also 2/'ignore').Also applies to: 14828-14831, 14866-14918
4011-4019: Minor DRY: generate consecutive‑group spacing tests across strategies.These blocks are basically identical under 'alphabetical', 'natural', and 'line‑length'. You could wrap them in
describe.each(['alphabetical','natural','line-length'])with a small helper to buildoptionsto reduce duplication. Optional, readability win only.Also applies to: 8661-8669, 13245-13253
docs/content/rules/sort-object-types.mdx (3)
322-322: Correct regex grouping in example.
'^r|g|b$'matches unintended strings. Prefer^(?:r|g|b)$(or^[rgb]$) to match exactly r/g/b.- allNamesMatchPattern: '^r|g|b$', + allNamesMatchPattern: '^(?:r|g|b)$',
342-342: Fix invalid glob-like regex.Use
'.*Metadata$'(regex) instead of'*Metadata$'.- declarationMatchesPattern: '*Metadata$', + declarationMatchesPattern: '.*Metadata$',
781-782: Update test link pathTests live under
test/rules/…. Update the “Test source” link.-- [Test source](https://github.com/azat-io/eslint-plugin-perfectionist/blob/main/test/sort-object-types.test.ts) +- [Test source](https://github.com/azat-io/eslint-plugin-perfectionist/blob/main/test/rules/sort-object-types.test.ts)docs/content/rules/sort-heritage-clauses.mdx (1)
442-443: Update test link pathPoint to
test/rules/sort-heritage-clauses.test.ts.-- [Test source](https://github.com/azat-io/eslint-plugin-perfectionist/blob/main/test/sort-heritage-clauses.test.ts) +- [Test source](https://github.com/azat-io/eslint-plugin-perfectionist/blob/main/test/rules/sort-heritage-clauses.test.ts)docs/content/rules/sort-variable-declarations.mdx (2)
297-305: Add'custom'totypeunion and consider richernewlinesInsidetyping.For parity with rule-level
typeand other pages, include'custom'; considernewlinesInside?: 'always' | 'never' | number.interface CustomGroupDefinition { groupName: string - type?: 'alphabetical' | 'natural' | 'line-length' | 'unsorted' + type?: 'alphabetical' | 'natural' | 'line-length' | 'custom' | 'unsorted' order?: 'asc' | 'desc' fallbackSort?: { type: string; order?: 'asc' | 'desc' } - newlinesInside?: number + newlinesInside?: 'always' | 'never' | number selector?: string elementNamePattern?: string | string[] | { pattern: string; flags?: string } | { pattern: string; flags?: string }[] } … interface CustomGroupAnyOfDefinition { groupName: string - type?: 'alphabetical' | 'natural' | 'line-length' | 'unsorted' + type?: 'alphabetical' | 'natural' | 'line-length' | 'custom' | 'unsorted' order?: 'asc' | 'desc' fallbackSort?: { type: string; order?: 'asc' | 'desc' } - newlinesInside?: number + newlinesInside?: 'always' | 'never' | number anyOf: Array<{ selector?: string elementNamePattern?: string | string[] | { pattern: string; flags?: string } | { pattern: string; flags?: string }[] }> }Also applies to: 313-324
423-424: Update test link pathPoint to
test/rules/sort-variable-declarations.test.ts.-- [Test source](https://github.com/azat-io/eslint-plugin-perfectionist/blob/main/test/sort-variable-declarations.test.ts) +- [Test source](https://github.com/azat-io/eslint-plugin-perfectionist/blob/main/test/rules/sort-variable-declarations.test.ts)docs/content/rules/sort-named-imports.mdx (2)
343-351: Include'custom'intypeunions and considernewlinesInsideparity.Align with top-level
typeand other docs.interface CustomGroupDefinition { groupName: string - type?: 'alphabetical' | 'natural' | 'line-length' | 'unsorted' + type?: 'alphabetical' | 'natural' | 'line-length' | 'custom' | 'unsorted' order?: 'asc' | 'desc' fallbackSort?: { type: string; order?: 'asc' | 'desc' } - newlinesInside?: number + newlinesInside?: 'always' | 'never' | number selector?: string elementNamePattern?: … } … interface CustomGroupAnyOfDefinition { groupName: string - type?: 'alphabetical' | 'natural' | 'line-length' | 'unsorted' + type?: 'alphabetical' | 'natural' | 'line-length' | 'custom' | 'unsorted' order?: 'asc' | 'desc' fallbackSort?: { type: string; order?: 'asc' | 'desc' } - newlinesInside?: number + newlinesInside?: 'always' | 'never' | number anyOf: Array<{ … }> }Also applies to: 359-370
471-472: Update test link pathPoint to
test/rules/sort-named-imports.test.ts.-- [Test source](https://github.com/azat-io/eslint-plugin-perfectionist/blob/main/test/sort-named-imports.test.ts) +- [Test source](https://github.com/azat-io/eslint-plugin-perfectionist/blob/main/test/rules/sort-named-imports.test.ts)docs/content/rules/sort-intersection-types.mdx (2)
390-398: Add'custom'totypeunions and considernewlinesInsideparity.Keep these interfaces consistent with rule-level
type.interface CustomGroupDefinition { groupName: string - type?: 'alphabetical' | 'natural' | 'line-length' | 'unsorted' + type?: 'alphabetical' | 'natural' | 'line-length' | 'custom' | 'unsorted' order?: 'asc' | 'desc' fallbackSort?: { type: string; order?: 'asc' | 'desc' } - newlinesInside?: number + newlinesInside?: 'always' | 'never' | number selector?: string elementNamePattern?: … } … interface CustomGroupAnyOfDefinition { groupName: string - type?: 'alphabetical' | 'natural' | 'line-length' | 'unsorted' + type?: 'alphabetical' | 'natural' | 'line-length' | 'custom' | 'unsorted' order?: 'asc' | 'desc' fallbackSort?: { type: string; order?: 'asc' | 'desc' } - newlinesInside?: number + newlinesInside?: 'always' | 'never' | number anyOf: Array<{ … }> }Also applies to: 406-416
516-517: Update test link pathPoint to
test/rules/sort-intersection-types.test.ts.-- [Test source](https://github.com/azat-io/eslint-plugin-perfectionist/blob/main/test/sort-intersection-types.test.ts) +- [Test source](https://github.com/azat-io/eslint-plugin-perfectionist/blob/main/test/rules/sort-intersection-types.test.ts)docs/content/rules/sort-array-includes.mdx (2)
391-398: Add'custom'totypeunions and considernewlinesInsideparity.Align with the top-level
typeand other pages.interface CustomGroupDefinition { groupName: string - type?: 'alphabetical' | 'natural' | 'line-length' | 'unsorted' + type?: 'alphabetical' | 'natural' | 'line-length' | 'custom' | 'unsorted' order?: 'asc' | 'desc' fallbackSort?: { type: string; order?: 'asc' | 'desc' } - newlinesInside?: number + newlinesInside?: 'always' | 'never' | number selector?: string elementNamePattern?: … } … interface CustomGroupAnyOfDefinition { groupName: string - type?: 'alphabetical' | 'natural' | 'line-length' | 'unsorted' + type?: 'alphabetical' | 'natural' | 'line-length' | 'custom' | 'unsorted' order?: 'asc' | 'desc' fallbackSort?: { type: string; order?: 'asc' | 'desc' } - newlinesInside?: number + newlinesInside?: 'always' | 'never' | number anyOf: Array<{ … }> }Also applies to: 406-417
516-517: Update test link pathPoint to
test/rules/sort-array-includes.test.ts.-- [Test source](https://github.com/azat-io/eslint-plugin-perfectionist/blob/main/test/sort-array-includes.test.ts) +- [Test source](https://github.com/azat-io/eslint-plugin-perfectionist/blob/main/test/rules/sort-array-includes.test.ts)docs/content/rules/sort-maps.mdx (1)
276-287: Allow 'ignore' in per-gap newlines type (keep docs in sync with behavior).Group-level
{ newlinesBetween: ... }should also accept'ignore', not justnumber. Tests use'ignore'in group descriptors elsewhere; align the public surface.- Array< + Array< | string | string[] - | { newlinesBetween: number } + | { newlinesBetween: number | 'ignore' } | { group: string | string[]; type: 'alphabetical' | 'natural' | 'line-length' | 'custom' | 'unsorted'; } >docs/content/rules/sort-interfaces.mdx (2)
304-314: New filters look good; makeflagsconsistently optional.Across docs you sometimes show
{ pattern; flags }and elsewhereflags?. Make it consistently optional to match typical RegExp options.- declarationCommentMatchesPattern?: string | string[] | { pattern: string; flags: string } | { pattern: string; flags: string }[] + declarationCommentMatchesPattern?: string | string[] | { pattern: string; flags?: string } | { pattern: string; flags?: string }[] - hasNumericKeysOnly?: boolean + hasNumericKeysOnly?: boolean
419-433: Allow 'ignore' in per-gap newlines type inside groups.Docs show
{ newlinesBetween: number }, but tests use'ignore'at the group level. Update the union for accuracy.- | { newlinesBetween: number } + | { newlinesBetween: number | 'ignore' }docs/content/rules/sort-sets.mdx (1)
271-285: Permit 'ignore' in per-gap newlines type inside groups.Align group descriptor type with actual behavior (allow
'ignore'as well as numbers).- | { newlinesBetween: number } + | { newlinesBetween: number | 'ignore' }docs/content/rules/sort-enums.mdx (1)
236-247: Allow 'ignore' for group-level newlinesBetween.To match tests and other rules, permit
'ignore'in group descriptors.- | { newlinesBetween: number } + | { newlinesBetween: number | 'ignore' }test/rules/sort-enums.test.ts (1)
4711-4760: Minor: newlinesBetween default examples across docs.In some rule pages, examples still use
newlinesBetween: false. Public type isnumber | 'ignore'. Recommend normalizing examples to'ignore'.docs/content/rules/sort-objects.mdx (2)
463-475: Allow 'ignore' in per-gap newlines type inside groups.Align with behavior used in tests for other rules.
- | { newlinesBetween: number } + | { newlinesBetween: number | 'ignore' }
258-272: Nit: terminate with semicolons consistently in TS examples.Optional, but keeping
;after object literals’ properties can reduce diffs in copy-paste.docs/content/rules/sort-exports.mdx (1)
216-229: Permit 'ignore' in per-gap newlines type inside groups.Bring group descriptor union in line with other rules.
- | { newlinesBetween: number } + | { newlinesBetween: number | 'ignore' }test/rules/sort-array-includes.test.ts (1)
1398-1723: CombinatorialnewlinesBetweentests are precise but quite verboseThe matrix of global vs inline
newlinesBetweenvalues (0,1,2,'ignore') plus unused groups and different error kinds (extraSpacing,missedSpacing) is very comprehensive and matches the documented precedence rules.If this starts to drift across rules, consider extracting shared helpers (e.g. a small generator for these option matrices) to keep maintenance manageable, but it’s optional at this point.
Also applies to: 3172-3496, 4927-5251
docs/content/rules/sort-decorators.mdx (1)
247-269: ClarifypartitionByNewLinesemanticsThe current text (“will not sort the decorators if there is an empty line between them”) can be read as “no sorting happens at all” when any blank line exists. Consider rephrasing to something like “treats decorators separated by empty lines as independent partitions and only sorts within each partition” to match the tests.
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (27)
docs/content/rules/sort-array-includes.mdx(4 hunks)docs/content/rules/sort-classes.mdx(3 hunks)docs/content/rules/sort-decorators.mdx(5 hunks)docs/content/rules/sort-enums.mdx(6 hunks)docs/content/rules/sort-export-attributes.mdx(1 hunks)docs/content/rules/sort-exports.mdx(3 hunks)docs/content/rules/sort-heritage-clauses.mdx(5 hunks)docs/content/rules/sort-import-attributes.mdx(1 hunks)docs/content/rules/sort-imports.mdx(5 hunks)docs/content/rules/sort-interfaces.mdx(7 hunks)docs/content/rules/sort-intersection-types.mdx(5 hunks)docs/content/rules/sort-jsx-props.mdx(7 hunks)docs/content/rules/sort-maps.mdx(2 hunks)docs/content/rules/sort-modules.mdx(3 hunks)docs/content/rules/sort-named-exports.mdx(2 hunks)docs/content/rules/sort-named-imports.mdx(2 hunks)docs/content/rules/sort-object-types.mdx(7 hunks)docs/content/rules/sort-objects.mdx(9 hunks)docs/content/rules/sort-sets.mdx(4 hunks)docs/content/rules/sort-union-types.mdx(4 hunks)docs/content/rules/sort-variable-declarations.mdx(2 hunks)test/rules/sort-array-includes.test.ts(41 hunks)test/rules/sort-classes.test.ts(27 hunks)test/rules/sort-decorators.test.ts(2 hunks)test/rules/sort-enums.test.ts(41 hunks)test/rules/sort-export-attributes.test.ts(1 hunks)test/rules/sort-exports.test.ts(49 hunks)
✅ Files skipped from review due to trivial changes (1)
- docs/content/rules/sort-import-attributes.mdx
🚧 Files skipped from review as they are similar to previous changes (3)
- docs/content/rules/sort-named-exports.mdx
- test/rules/sort-export-attributes.test.ts
- docs/content/rules/sort-export-attributes.mdx
🔇 Additional comments (44)
docs/content/rules/sort-union-types.mdx (4)
235-246: Type definition for groups option is well-structured and clear.The union type correctly represents the new array-based groups API with per-group overrides (newlinesBetween objects and type overrides). This aligns with the v5.0.0 API migration and is documented clearly with the nested structure.
320-320: Code fence language changes fromjstotsare appropriate.The examples in these code blocks use TypeScript syntax (e.g.,
groups: [...]with type-aware grouping), so the language specifier change is correct and improves syntax highlighting for readers.Also applies to: 356-356
366-379: Per-group overrides section is clear and well-integrated.The "Group with overridden settings" section effectively documents the new capability to override options (like
type) per-group. The example is concise and directly illustrates the feature.
232-248: Consider adding a migration notice for customGroups API changes (if applicable).The
sort-union-typesrule documentation lacks a migration notice for thecustomGroupsoption, whereassort-classesincludes one at lines 641–667 of its file. If the customGroups API for union types was also changed (from object-based to array-based), please add a similar migration notice to aid users upgrading to v5.0.0.Does the
sort-union-typesrule'scustomGroupsoption have breaking API changes in v5.0.0? If so, a migration notice similar to the one insort-classes.mdxshould be added.docs/content/rules/sort-classes.mdx (5)
327-338: Type definition for groups option is consistent with sort-union-types.mdx.The union type mirrors the structure from
sort-union-typesdocumentation, ensuring consistency across rules. Per-group overrides (newlinesBetween objects and type overrides) are clearly represented.
342-359: Comprehensive default groups configuration is well-documented.The default
groupsarray is extensive and covers all selector and modifier combinations for class members (index-signature, static properties, accessors, constructor, methods, etc.). The structure is clear and the comments explain each group's purpose.Please verify that this default groups configuration exactly matches the actual implementation in
rules/sort-classes/index.tsor the corresponding rule file to ensure documentation accuracy.
605-618: Per-group overrides section aligns well with sort-union-types documentation.The "Group with overridden settings" section provides a clear, concise example of overriding the
typeoption for a specific group. The example demonstrates the feature without unnecessary complexity.
641-667: Migration notice for breaking customGroups API change is helpful and clear.The notice at lines 641–667 effectively communicates the breaking change from object-based to array-based
customGroupsconfiguration. The before/after code example makes migration straightforward for users upgrading to v5.0.0.
738-783: Verify code fence language and syntax highlighting.The customGroups example uses
tslanguage specifier. Ensure the TypeScript syntax in the example is highlighted correctly and that the code block is properly formatted for readability on the documentation site.Please confirm that the code fence rendering (lines 738–783) displays correctly on the documentation site and that TypeScript syntax highlighting is applied appropriately.
test/rules/sort-classes.test.ts (3)
4011-4021: Numeric newlinesBetween migration LGTM.Using numeric values (0/1/2) and 'ignore' per-group/global is clear and consistent with the new API. No issues spotted.
Also applies to: 8661-8671, 13245-13255
13998-14028: Great test for per‑group overrides.Verifies that a group can override the global
type. This guards the new options shape well.
4279-4324: Partition + newlinesBetween = 0: scenario reads well.Good coverage to ensure spacing fixes don’t cross partitions. No changes requested.
Also applies to: 8930-8974, 13513-13559
test/rules/sort-exports.test.ts (2)
527-553: Good coverage for per-group option overrides.Validates that a group-level
typeoverride works with globaltype: 'unsorted'. LGTM.
867-921: Solid test fornewlinesBetween: 0removal behavior.Covers both spacing diagnostics and reordering. LGTM.
docs/content/rules/sort-maps.mdx (1)
301-314: Good: per‑group overrides section reads clearly.No changes requested. Consider noting if
order/fallbackSortcan also be overridden here for parity withcustomGroups.docs/content/rules/sort-interfaces.mdx (1)
699-718: Nice example with group names; LGTM.Clear migration to array-based
customGroupsand combined groups.docs/content/rules/sort-sets.mdx (2)
284-284: Default groups update to ['literal'] — LGTM.
303-316: Per‑group overrides section reads well.No changes requested.
docs/content/rules/sort-enums.mdx (1)
261-274: Per‑group overrides example — LGTM.test/rules/sort-enums.test.ts (1)
1288-1330: Tests demonstrate 'ignore' allowed in group newlines descriptors. Sync docs.Multiple cases use
{ newlinesBetween: 'ignore' }insidegroups. Please ensure all rule docs (enums, interfaces, objects, sets, maps, exports) reflect this union at group level.Also applies to: 1390-1435, 1437-1486
docs/content/rules/sort-objects.mdx (1)
712-731: Example reads well; migration is clear.docs/content/rules/sort-exports.mdx (2)
183-194: Good partitionByNewLine example.Reads clearly.
262-301: commentAbove docs are clear and actionable.Nice addition; behavior and auto-fix semantics are well explained.
test/rules/sort-array-includes.test.ts (4)
262-312: Group-order error coverage forspreadvsunknownlooks correctThe added
groups: ['spread']plusleftGroup/rightGroupandmessageId: 'unexpectedArrayIncludesGroupOrder'assertions exercise the new group-order diagnostics consistently across alphabetical, natural, and line-length modes. No issues spotted.Also applies to: 2070-2120, 3825-3873
840-871: Good regression test for per-grouptypeoverrideUsing global
type: 'unsorted'withgroups: [{ type: 'alphabetical', group: 'unknown' }]is a nice way to lock in that group-local sort settings win over the global mode. The expectations for both error and output match that intent.
1366-1395:newlinesBetween: 0behavior is well specified and testedThese cases correctly assert:
- extra-spacing diagnostics when blank lines exist between groups with
newlinesBetween: 0- that auto-fix removes those blank lines without disturbing order semantics.
The triplicated coverage for all three sort modes is thorough.
Also applies to: 3110-3169, 4865-4924
1771-1819: Partition boundaries preserved despitenewlinesBetween: 0The “preserves partition boundaries regardless of
newlinesBetween 0” tests correctly lock in thatpartitionByComment: truesegments are never merged or reordered across the partition comment, even when global newlines are forced to zero. Behavior and expectations are consistent.Also applies to: 3545-3593, 5300-5348
test/rules/sort-decorators.test.ts (6)
471-533: Per-group override test for decorators matches the intended APIThe “allows overriding options in groups” case mirrors the array-includes behavior: a global
type: 'unsorted'withgroups: [{ type: 'alphabetical', group: 'unknown' }]and 5 contexts covered viaduplicate5Times. Error IDs and outputs look consistent.
535-623: Solid coverage ofelementNamePatternvariants in custom groupsThe
it.eachblock that exercises string, array, and regex (including in arrays) patterns forelementNamePatternis a good regression guard that the custom grouping logic accepts all supported shapes and emitsunexpectedDecoratorsGroupOrderwith the rightleftGroup/rightGroup.
624-914: Custom-group sort/type overrides and unsorted behavior are well testedThe new tests around:
- overriding
type/orderfor a Foo-containing group,- per-group
fallbackSorton ties, and- preserving original order for
type: 'unsorted'groups and negative regex patternstogether give strong coverage of the richer
customGroupsAPI for decorators. Expectations and options structures are coherent with the docs.
916-1271: Newline behavior between decorator groups is exhaustively coveredThe
newlinesBetweentests for decorators (0 vs 1 vs 2 vs'ignore', plus inline overrides ingroups) carefully distinguish:
- extra vs missed spacing diagnostics,
- precedence between global and inline settings, and
- the “accept any spacing” combinations.
This aligns with the array-includes tests and should make regressions here unlikely.
1361-1555:newlinesInsideandpartitionByNewLinesemantics are nailed downThe
newlinesInside: 1/0tests, plus “sorts within newline-separated partitions” and “preserves partition boundaries regardless ofnewlinesBetween 0”, give clear expectations for:
- intra-group spacing constraints, and
- how newline partitions limit reordering.
The chosen error IDs (
missedSpacingBetweenDecorators/extraSpacingBetweenDecorators/unexpectedDecoratorsOrder) look correct for each scenario.
2877-2927: Natural-mode JSDoc handling stays consistent with alphabetical testsThe natural-sort variants of “handles JSDoc comments before decorators correctly” now mirror the alphabetical ones, including the “Not a JSDoc comment” case. This keeps comment movement semantics uniform across sort types.
docs/content/rules/sort-decorators.mdx (3)
270-337:groupsshape and per-group override docs align with testsThe documented
groupsunion (strings, arrays,{ newlinesBetween }, and{ group, type }) plus the “Group with overridden settings” and “Newlines between groups” sections match how the tests configure per-group overrides and inline newline rules. No changes needed here.
441-453: Docs example forcustomGroupsnow matches the new array APIThe migration snippet from the old object-based
customGroupsto the new array-of-definitions form is clear and matches how tests configure decorators custom groups. Nice addition.
441-454: Updated default config snippet reflects new optionsThe “Usage” code samples show
partitionByNewLine,partitionByComment,newlinesBetween,groups: [], andcustomGroups: []with sensible defaults that align with the tests. This is consistent with the new rule surface.Also applies to: 458-484
docs/content/rules/sort-imports.mdx (3)
285-315: Comprehensive API expansion well-documented.The redesigned
groupsoption (lines 288–300) with union types for string, string[], newlinesBetween, and per-group config objects is clearly specified. The default groups example (lines 304–315) properly reflects the array-based structure. New selector (tsconfig-path, line 338) and modifiers (multiline,singleline, lines 360–361) fit logically into the existing hierarchy.
452-491: New sections on per-group overrides and newline control are well-explained.Both "Group with overridden settings" (lines 452–472) and "Newlines between groups" (lines 474–491) clearly document the new per-group configuration capabilities:
group,commentAbove,typefields, and placement ofnewlinesBetweenobjects as distinct array elements. Examples are practical and reinforce the intent.
602-626: Example code properly demonstrates array-basedcustomGroupsmigration.The example (lines 602–626) shows migration from object to array-based
customGroupswithgroupNameandelementNamePatternproperties. The react and lodash group definitions are clear and align with the documented API.docs/content/rules/sort-jsx-props.mdx (5)
270-283: Array-basedcustomGroupsAPI properly documented.The migration from object-map to array-based format with
groupNameandelementNamePatternis clear. Each group definition follows the documented interface correctly.
318-329: Updatedgroupstype definition aligns withsort-imports.mdx.The expanded union type for
groups(lines 318–329) supports string, string[],newlinesBetween, and per-group config objects, consistent with the sort-imports rule documentation.
356-369: New "Group with overridden settings" section is clear.The section (lines 356–369) properly documents per-group
typeoverrides with a practical example showing how'shorthand'props can remain unsorted while multiline props are sorted.
530-530: Config examples correctly updated to array-basedcustomGroupsdefault.Both flat and legacy config examples (lines 530, 560) now show
customGroups: []reflecting the new API default, replacing the prior object-based format.Also applies to: 560-560
582-582: Test source link updated to new path.Line 582 updates the test source link to
test/rules/sort-jsx-props.test.ts, reflecting the migration to Vitest as documented in the PR objectives.
| ### 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. | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Replace “class decorators” with “heritage clauses”.
This rule is about extends/implements. The section mistakenly refers to “class decorators”.
- Enables the use of comments to separate class decorators into logical groups.
+ Enables the use of comments to separate heritage clauses into logical groups.🤖 Prompt for AI Agents
In docs/content/rules/sort-heritage-clauses.mdx around lines 148 to 159, the
text incorrectly refers to “class decorators”; update those occurrences to
“heritage clauses” so the description reads that comments separate heritage
clauses (i.e., extends/implements). Keep the rest of the option descriptions
unchanged and ensure the heading/subtext semantics remain intact.
| #### Group with overridden settings | ||
| You may directly override options for a specific group by using an object with the `group` property and other option overrides. | ||
| - `type` — Overrides the [`type`](#type) option for that group. | ||
| ```ts | ||
| { | ||
| groups: [ | ||
| 'method', | ||
| { group: 'multiline-member', type: 'unsorted' }, // Elements from this group will not be sorted | ||
| ] | ||
| } | ||
| ``` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unclosed code fence above breaks MDX rendering.
The “Example 2” code block started earlier isn’t closed before this heading. Close the block (and the interface brace if needed) to avoid layout/anchor issues.
interface Interface {
// 'index-signature'
[key: string]: any;
// 'optional-property'
description?: string;
// 'required-method'
method(): string
-```
+}
+```Committable suggestion skipped: line range outside the PR's diff.
🤖 Prompt for AI Agents
In docs/content/rules/sort-interfaces.mdx around lines 547 to 560, the prior
example's code fence (and the closing interface brace if the example left one
open) is missing which breaks MDX rendering; fix it by adding the required
closing brace(s) and terminating the fenced code block (```), ensuring the
example is syntactically complete before the "Group with overridden settings"
heading so the MDX parses correctly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
♻️ Duplicate comments (1)
rules/sort-imports/types.ts (1)
37-40: Fix malformed JSDoc@defaulttag fortsconfig.filename.The JSDoc currently splits the
@defaulttag across lines and leaves a stray quote (tsconfig.json'.), which makes the comment malformed and less useful to tooling.Consider updating it to a standard
@defaultannotation:- /** - * Optional filename of the TypeScript config file. `@default` - * tsconfig.json'. - */ + /** + * Optional filename of the TypeScript config file. + * @default 'tsconfig.json' + */
🧹 Nitpick comments (3)
rules/sort-object-types/types.ts (1)
164-179: Consider reviewing the 'multiline' entry in AllowedModifiersPerSelector.The
AllowedModifiersPerSelectorinterface includes a'multiline'key at line 174, but'multiline'is not a valid selector in theSelectorunion type (lines 144-148). SinceBaseSingleCustomGroup<T extends Selector>constrainsTto theSelectortype, this entry appears unreachable through the type system.While this may be pre-existing code unrelated to the current PR, it could be confusing for maintainers. Consider removing the unused
'multiline'entry or clarifying its purpose if it serves a specific role.rules/sort-imports/types.ts (1)
170-188: Selectors/modifiers and JSON schema are coherent; consider tightening type/schema alignment.The following pieces line up well:
SelectorandModifierunions now explicitly include all string literal variants used by the rule (including the newsingleline/multilinemodifiers).allSelectorsandallModifiersenumerate exactly those variants, which is important forvalidateGeneratedGroupsConfigurationand schema generation.singleCustomGroupJsonSchemausesbuildCustomGroupModifiersJsonSchema(allModifiers)andbuildCustomGroupSelectorJsonSchema(allSelectors), so schema validation stays in sync with the unions.Two optional improvements you might consider:
Derive union types from the arrays to avoid future drift, e.g.:
export const allSelectors = [ 'side-effect-style', 'tsconfig-path', // ... ] as const export type Selector = (typeof allSelectors)[number]and similarly for modifiers. That guarantees compile-time alignment between the arrays and the unions.
Align
SingleCustomGroupwith the JSON schema: the schema exposes bothelementValuePatternandelementNamePattern, whileSingleCustomGrouphere only typeselementNamePattern. IfelementValuePatternis intentionally unsupported forsort-imports, consider dropping it from this schema; otherwise, add it as an optional property toSingleCustomGroupso TS users and JSON schema see the same surface.Also applies to: 205-216, 247-252, 331-342, 348-352
rules/sort-imports.ts (1)
115-123: Consider guarding tsconfig resolution onoptions.tsconfigrather thanrootDirtruthiness.The current logic only resolves a tsconfig when
options.tsconfig?.rootDiris truthy:let tsconfigRootDirectory = options.tsconfig?.rootDir let tsConfigOutput = tsconfigRootDirectory ? readClosestTsConfigByPath({ /* ... */ }) : nullThis will skip resolution if someone (perhaps accidentally) configures
rootDir: ''. If you want any providedtsconfigobject to be honored regardless of whetherrootDiris an empty string or'./', consider keying the condition off the presence ofoptions.tsconfiginstead:- let tsconfigRootDirectory = options.tsconfig?.rootDir - let tsConfigOutput = tsconfigRootDirectory - ? readClosestTsConfigByPath({ - tsconfigFilename: options.tsconfig?.filename ?? 'tsconfig.json', - tsconfigRootDir: tsconfigRootDirectory, + let tsConfig = options.tsconfig + let tsConfigOutput = tsConfig + ? readClosestTsConfigByPath({ + tsconfigFilename: tsConfig.filename ?? 'tsconfig.json', + tsconfigRootDir: tsConfig.rootDir, filePath: context.physicalFilename, contextCwd: context.cwd, }) : nullThis also avoids repeating the optional chaining on
options.tsconfig.
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
rules/sort-imports.ts(9 hunks)rules/sort-imports/types.ts(6 hunks)rules/sort-object-types/types.ts(3 hunks)
🧰 Additional context used
🧬 Code graph analysis (3)
rules/sort-object-types/types.ts (3)
types/common-options.ts (3)
RegexOption(458-458)CustomGroupsOption(103-134)FallbackSortOption(274-286)rules/sort-objects/types.ts (1)
SingleCustomGroup(122-138)types/join-with-dash.ts (1)
JoinWithDash(4-4)
rules/sort-imports/types.ts (2)
types/common-options.ts (1)
CustomGroupsOption(103-134)rules/sort-jsx-props/types.ts (2)
SingleCustomGroup(80-105)Selector(117-117)
rules/sort-imports.ts (7)
rules/sort-imports/types.ts (5)
Options(29-141)allSelectors(311-325)allModifiers(331-342)Selector(174-187)Modifier(205-215)utils/validate-newlines-and-partition-configuration.ts (1)
validateNewlinesAndPartitionConfiguration(98-119)rules/sort-imports/validate-side-effects-configuration.ts (1)
validateSideEffectsConfiguration(19-48)utils/is-node-on-single-line.ts (1)
isNodeOnSingleLine(9-11)utils/common-json-schemas.ts (1)
buildCustomGroupsArrayJsonSchema(324-373)utils/generate-predefined-groups.ts (1)
generatePredefinedGroups(23-56)utils/compute-group.ts (1)
computeGroup(77-115)
🔇 Additional comments (10)
rules/sort-object-types/types.ts (4)
35-39: LGTM!The new
declarationCommentMatchesPatternfield is well-documented and follows the established pattern naming convention.
53-57: LGTM!The new
hasNumericKeysOnlyfield is well-defined and clearly documented.
60-67: LGTM!The migration to array-based
CustomGroupsOptionaligns with the PR objectives. The type parameters and additional options are well-structured.
231-240: LGTM!The new
PropertyGrouptype definition follows the same pattern as other group types and properly replaces the deprecatedMultilineGroup. The JSDoc documentation clearly explains its purpose.rules/sort-imports/types.ts (1)
46-48: Custom groups option wiring looks correct.
customGroups: CustomGroupsOption<SingleCustomGroup>is consistent withCustomGroupsOptionfromtypes/common-options.tsand theSingleCustomGroupdefinition here, so the public options surface forsort-importsmatches the shared custom-groups abstraction.rules/sort-imports.ts (5)
43-43: Single-line vs multiline modifiers are wired consistently.Using
isNodeOnSingleLine(node)to always append exactly one of'singleline'or'multiline'tomodifierskeeps the modifier set mutually exclusive for line-shape, and matches the newModifierunion andallModifiersinrules/sort-imports/types.ts. This should integrate cleanly with group computation and validation.Also applies to: 214-218
67-71: defaultOptions typing and reuse across rule/meta look solid.Typing
defaultOptionsas:Required<Omit<Options[number], 'maxLineLength' | 'tsconfig'>> & Pick<Options[number], 'maxLineLength' | 'tsconfig'>ensures all non-
maxLineLength/tsconfigfields are explicitly populated while keeping those two optional. Reusing the samedefaultOptionsobject for bothmeta.defaultOptionsand the rule’sdefaultOptionskeeps the public API and runtime defaults in sync.Also applies to: 450-455
106-113: Custom-groups flow, group computation, and schema wiring are coherent.A few related pieces look well-aligned:
validateGeneratedGroupsConfiguration({ selectors: allSelectors, modifiers: allModifiers, options })ensures the resolved options (defaults + user config) are validated against the authoritative selector/modifier sets fromrules/sort-imports/types.ts.getCustomGroupOverriddenOptions({ groupIndex, options })is now called with the full resolved options, and the subsequent logic preserves the "side-effect groups are unsorted when sortSideEffects is false" behavior by overridingtypeto'unsorted'only for pure side-effect groups.customGroupsin the schema usesbuildCustomGroupsArrayJsonSchema({ singleCustomGroupJsonSchema }), so the runtime JSON schema now matches the new array-based custom-groups shape defined inrules/sort-imports/types.ts.computeGroupExceptUnknowncleanly wrapsgeneratePredefinedGroupsandcomputeGroup, returningnullfor the'unknown'case; the caller then normalizes this back to'unknown'via?? 'unknown', so behavior stays the same while providing a reusable helper if needed elsewhere.Overall, the custom-groups pipeline (options → validation → JSON schema → runtime group computation) looks consistent.
Also applies to: 312-338, 422-424, 450-455, 530-561
355-369: Passing resolved options intoreportAllErrorsis a good enhancement.Including
optionsin thereportAllErrorscall gives the reporting layer access to the fully-resolved configuration (defaults + user overrides), which can be useful for context-aware diagnostics or future behavior toggles, without changing the core sorting logic.
372-381: Optional chaining onVariableDeclarationinit prevents crashes.The additional
?.onnode.declarations[0].initavoids accessing.typeonundefinedwhen handlingVariableDeclarations that don’t have an initializer, while preserving the existing require-call detection logic.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
docs/content/rules/sort-jsx-props.mdx (1)
299-307:tagMatchesPatternexample uses invalid regexp syntax.The example value
'*Component$'is not a valid JavaScript regular expression pattern (a leading*is illegal). If the intent is “names ending withComponent”, it should be:- tagMatchesPattern: '*Component$', + tagMatchesPattern: '.*Component$',(or simply
'Component$'if a.*prefix is unnecessary).
♻️ Duplicate comments (12)
docs/content/rules/sort-jsx-props.mdx (1)
269-286: FixallNamesMatchPatternRGB regex anchoring.
'^r|g|b$'is parsed as(^r) | g | (b$), so it will match many unintended names (any containingg, any ending withb, etc.). To match only props named exactly'r','g', or'b', wrap the alternation in a single anchored group:- allNamesMatchPattern: '^r|g|b$', + allNamesMatchPattern: '^(?:r|g|b)$',docs/content/rules/sort-heritage-clauses.mdx (2)
148-159: Replace "class decorators" with "heritage clauses".This section incorrectly refers to "class decorators" when it should refer to "heritage clauses" (i.e.,
extends/implementsclauses).Apply this diff:
-Enables the use of comments to separate class decorators into logical groups. +Enables the use of comments to separate heritage clauses into logical groups.
308-319: Verify type union completeness for CustomGroupAnyOfDefinition.The
typeoption on line 310 is missing'custom', which is documented as a valid option elsewhere in this file (line 73). For consistency with CustomGroupDefinition (lines 293-300), ensure the type union includes all valid options.Apply this diff:
interface CustomGroupAnyOfDefinition { groupName: string - type?: 'alphabetical' | 'natural' | 'line-length' | 'unsorted' + type?: 'alphabetical' | 'natural' | 'line-length' | 'custom' | 'unsorted' order?: 'asc' | 'desc' fallbackSort?: { type: string; order?: 'asc' | 'desc' } newlinesInside?: numberrules/sort-imports/types.ts (1)
24-38: Fix malformed JSDoc comment.The JSDoc comment has a malformed
@defaultannotation with mismatched quotes.Apply this diff:
/** - * Optional filename of the TypeScript config file. `@default` - * tsconfig.json'. + * Optional filename of the TypeScript config file. + * @default 'tsconfig.json' */docs/content/rules/sort-export-attributes.mdx (2)
146-157: Remove unsupportednewlinesBetweenvalues.The documentation lists
'always'and'never'as valid values, but according to past review comments, the actual implementation only supports'ignore'andnumber.Apply this diff:
-<sub>type: `number | 'ignore' | 'always' | 'never'`</sub> +<sub>type: `number | 'ignore'`</sub> <sub>default: `'ignore'`</sub> Controls newlines between groups: - `'ignore'` — Do not report spacing issues. -- `'always'` — Require a blank line between groups, forbid blank lines inside a group. -- `'never'` — Forbid blank lines between groups. - `number` — Require exactly that many newlines between groups; forbid inside a group.
226-244: FixnewlinesInsidetype definition.The type annotation shows
'always' | 'never' | number, but according to past review comments, the implementation only acceptsnumber.Apply this diff:
// Optional per-group overrides: type?: 'alphabetical' | 'natural' | 'line-length' | 'custom' | 'unsorted' order?: 'asc' | 'desc' fallbackSort?: { type: string; order?: 'asc' | 'desc' } - newlinesInside?: 'always' | 'never' | number + newlinesInside?: number }[]docs/content/rules/sort-modules.mdx (1)
501-545: Fix trailing.inelementNamePatternin the customGroups exampleIn the
input-types-and-interfacesexample, bothelementNamePattern: 'Input'.andelementNamePattern: 'Input'.end with a trailing dot, which makes the snippet invalid TypeScript. Drop the dot so it becomeselementNamePattern: 'Input'.The “Test source” link now correctly targets
test/rules/sort-modules.test.ts.rules/sort-export-attributes.ts (1)
9-40: Wire innewlinesBetweenValueGetterso spacing/newline diagnostics workThe rule collects attributes, partitions them, and calls
reportAllErrors, but it never suppliesnewlinesBetweenValueGetter. That means thenewlinesBetweenoption and the spacing-related messages (missedSpacingBetweenExportAttributes/extraSpacingBetweenExportAttributes) cannot function as intended.You already have
getLinesBetweenin the shared utils; the rule just needs to hook it up.Suggested patch:
@@ -import { sortNodesByGroups } from '../utils/sort-nodes-by-groups' +import { sortNodesByGroups } from '../utils/sort-nodes-by-groups' +import { getLinesBetween } from '../utils/get-lines-between' @@ for (let nodes of formattedMembers) { @@ function createSortNodesExcludingEslintDisabled( sortingNodes: SortExportAttributesSortingNode[], ) { @@ } reportAllErrors<MessageId>({ availableMessageIds: { missedSpacingBetweenMembers: 'missedSpacingBetweenExportAttributes', extraSpacingBetweenMembers: 'extraSpacingBetweenExportAttributes', unexpectedGroupOrder: 'unexpectedExportAttributesGroupOrder', unexpectedOrder: 'unexpectedExportAttributesOrder', }, sortNodesExcludingEslintDisabled: createSortNodesExcludingEslintDisabled(nodes), + newlinesBetweenValueGetter: (left, right) => + getLinesBetween(sourceCode, left, right), sourceCode, options, context, nodes, }) }After this change,
newlinesBetween(both global and per-group) should start producing the expected spacing errors for export attributes. Please run the sort-export-attributes tests to confirm behavior.Also applies to: 86-163
rules/sort-enums/types.ts (1)
35-48: ClarifysortByValueJSDoc to document all three string literals.The type now exposes
'ifNumericEnum' | 'always' | 'never', but the comment only explains"always"and"never"and doesn’t describe what'ifNumericEnum'does. That makes the generated docs and types harder to interpret.Consider updating the block along these lines:
- /** - * Whether to sort enum members by their values instead of names. When - * "always", compares enum values; when "never", compares enum member - * names. - * - * @default ifNumericEnum - */ - sortByValue: 'ifNumericEnum' | 'always' | 'never' + /** + * Controls when enum members should be ordered by their values instead of their names. + * + * - `'always'` — compare enum member values for every enum. + * - `'never'` — keep name-based ordering regardless of values. + * - `'ifNumericEnum'` — sort by value only when every member has a numeric initializer; otherwise, sort by name. + * + * @default 'ifNumericEnum' + */ + sortByValue: 'ifNumericEnum' | 'always' | 'never'docs/content/rules/sort-interfaces.mdx (1)
538-546: Close theinterfacein “Example 2” for a syntactically complete snippet.The code block ends without a closing
}forinterface Interface, which makes the example invalid TypeScript even though the fence is now closed. Adding the brace keeps the example self‑contained:interface Interface { // 'index-signature' [key: string]: any; // 'optional-property' description?: string; // 'required-method' method(): string -``` +} +```docs/content/rules/sort-decorators.mdx (2)
380-387: Correct the TypeScript interface types.The
CustomGroupDefinitioninterface has incorrect type definitions that were previously flagged:
fallbackSortshould use a specific type union instead oftype: stringnewlinesInsideshould accept'always' | 'never' | numberinstead of justnumberThese types should match the runtime type definitions.
Based on learnings
547-547: Verify the test source link path.A previous review flagged this link as potentially pointing to the wrong path. Ensure it correctly references
test/rules/sort-decorators.test.ts.Based on learnings
🧹 Nitpick comments (8)
docs/content/rules/sort-jsx-props.mdx (1)
357-371: Align group names in overridden-settings example with documented selector/modifier format.Earlier in the doc you state that selectors end with
propand giveshorthand-propas the example group name; here the example uses bare'multiline'and'shorthand', which can be confusing. To keep terminology consistent with the rule’s group naming (selector + modifiers), consider:- groups: [ - 'multiline', - { group: 'shorthand', type: 'unsorted' }, // Elements from this group will not be sorted - ] + groups: [ + 'multiline-prop', + { group: 'shorthand-prop', type: 'unsorted' }, // Elements from this group will not be sorted + ]rules/sort-jsx-props/types.ts (1)
47-52: AlignselectorJSDoc with the narrowedSelectortype.
SingleCustomGroup.selector’s comment still claims it “can be 'prop', 'multiline', or 'shorthand'”, butSelectoris nowPropertySelector('prop'only), with multiline/shorthand modeled via themodifiersarray instead. Please update this JSDoc (and any related docs) so it reflects thatselectoris just'prop'and multiline/shorthand are expressed exclusively as modifiers.Also applies to: 90-95
rules/sort-object-types/types.ts (1)
141-156: Consider removing the now-unused ‘multiline’ selector mapping for clarityWith
PropertyGroupadded and theGroupunion now based onIndexSignatureGroup | PropertyGroup | MethodGroup | MemberGroup, there is noMultilineSelectorinSelectorandSingleCustomGroupno longer uses a'multiline'selector. TheAllowedModifiersPerSelector['multiline']entry therefore appears unreachable and can be removed (along with its comment) to reduce mental overhead for future contributors.Also applies to: 199-207, 208-233
docs/content/rules/sort-import-attributes.mdx (1)
226-242: EnsureCustomGroupdoc type matches the actual rule typingsThe
CustomGroupexample type (includingelementNamePatternandnewlinesInside?: 'always' | 'never' | number) looks reasonable, but it needs to stay exactly in sync withSingleCustomGroup/CustomGroupsOptioninrules/sort-import-attributes/types.ts.Please quickly confirm that:
elementNamePattern’s documented union matches theRegexOption/pattern type used in the rule, andnewlinesInside’s allowed values reflect what the implementation actually supports.If there’s any drift, updating either the typings or this snippet will keep users from guessing.
docs/content/rules/sort-sets.mdx (1)
271-283: Consider documenting'ignore'for per‑groupnewlinesBetweenif it’s supported.The
groupstype snippet currently restricts{ newlinesBetween: ... }tonumber, while the globalnewlinesBetweenoption allowsnumber | 'ignore'. If group-level objects also accept'ignore'(as other rules’ tests suggest), it’s worth reflecting that here to avoid under‑documenting the API.Also applies to: 304-318
docs/content/rules/sort-interfaces.mdx (1)
421-435: Optional: align per‑groupnewlinesBetweendocs with the global option.The
groupstype currently shows{ newlinesBetween: number }, while the globalnewlinesBetweenoption supportsnumber | 'ignore'. If the implementation also accepts'ignore'in group objects (as tests for other rules suggest), consider reflecting that here to avoid confusion between the two surfaces.Also applies to: 548-562
test/rules/sort-enums.test.ts (1)
552-655: New tests thoroughly exercisesortByValue, per‑group overrides, andnewlinesBetweensemantics.The added cases cover all three
sortByValuemodes, complex numeric enum detection, global vs per‑groupnewlinesBetween, and interactions with partitions and custom groups, which should make regressions in these areas unlikely. If you ever want to trim duplication, many of the newlinesBetween scenarios are structurally identical across the alphabetical/natural/line‑length suites and could be parameterized withdescribe.each, but that’s optional.Also applies to: 1157-1615, 2688-3126, 4163-4601
docs/content/rules/sort-exports.mdx (1)
215-229: Docs forgroupslook good; you might clarify per‑groupnewlinesBetweentype.The new
groupsunion andcommentAboveexplanation nicely match the rule’s richer grouping API. One small nit: the snippet types{ newlinesBetween: number }, while the top-levelnewlinesBetweenoption allowsnumber | 'ignore'. If group-level objects also accept'ignore', consider reflecting that here so the two surfaces stay in sync.Also applies to: 263-303
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (48)
docs/content/rules/sort-array-includes.mdx(5 hunks)docs/content/rules/sort-classes.mdx(4 hunks)docs/content/rules/sort-decorators.mdx(6 hunks)docs/content/rules/sort-enums.mdx(6 hunks)docs/content/rules/sort-export-attributes.mdx(1 hunks)docs/content/rules/sort-exports.mdx(4 hunks)docs/content/rules/sort-heritage-clauses.mdx(6 hunks)docs/content/rules/sort-import-attributes.mdx(1 hunks)docs/content/rules/sort-imports.mdx(6 hunks)docs/content/rules/sort-interfaces.mdx(8 hunks)docs/content/rules/sort-intersection-types.mdx(6 hunks)docs/content/rules/sort-jsx-props.mdx(7 hunks)docs/content/rules/sort-maps.mdx(3 hunks)docs/content/rules/sort-modules.mdx(4 hunks)docs/content/rules/sort-named-exports.mdx(3 hunks)docs/content/rules/sort-named-imports.mdx(3 hunks)docs/content/rules/sort-object-types.mdx(8 hunks)docs/content/rules/sort-objects.mdx(9 hunks)docs/content/rules/sort-sets.mdx(5 hunks)docs/content/rules/sort-switch-case.mdx(1 hunks)docs/content/rules/sort-union-types.mdx(5 hunks)docs/content/rules/sort-variable-declarations.mdx(4 hunks)rules/sort-array-includes/types.ts(2 hunks)rules/sort-classes/types.ts(2 hunks)rules/sort-decorators/types.ts(1 hunks)rules/sort-enums/types.ts(2 hunks)rules/sort-export-attributes.ts(1 hunks)rules/sort-export-attributes/types.ts(1 hunks)rules/sort-exports/types.ts(2 hunks)rules/sort-heritage-clauses/types.ts(1 hunks)rules/sort-import-attributes.ts(1 hunks)rules/sort-import-attributes/types.ts(1 hunks)rules/sort-imports/types.ts(5 hunks)rules/sort-jsx-props/types.ts(4 hunks)rules/sort-maps/types.ts(2 hunks)rules/sort-modules/types.ts(2 hunks)rules/sort-named-exports/types.ts(2 hunks)rules/sort-named-imports/types.ts(2 hunks)rules/sort-object-types/build-node-value-getter.ts(2 hunks)rules/sort-object-types/types.ts(5 hunks)rules/sort-objects/types.ts(6 hunks)rules/sort-union-types/types.ts(2 hunks)rules/sort-variable-declarations/types.ts(2 hunks)test/rules/sort-array-includes.test.ts(42 hunks)test/rules/sort-classes.test.ts(27 hunks)test/rules/sort-decorators.test.ts(2 hunks)test/rules/sort-enums.test.ts(41 hunks)test/rules/sort-export-attributes.test.ts(1 hunks)
✅ Files skipped from review due to trivial changes (1)
- docs/content/rules/sort-switch-case.mdx
🚧 Files skipped from review as they are similar to previous changes (7)
- docs/content/rules/sort-intersection-types.mdx
- test/rules/sort-export-attributes.test.ts
- rules/sort-import-attributes.ts
- docs/content/rules/sort-named-imports.mdx
- test/rules/sort-classes.test.ts
- rules/sort-export-attributes/types.ts
- rules/sort-heritage-clauses/types.ts
🧰 Additional context used
🧬 Code graph analysis (18)
rules/sort-object-types/build-node-value-getter.ts (1)
utils/unreachable-case-error.ts (1)
UnreachableCaseError(31-43)
rules/sort-enums/types.ts (3)
types/common-groups-options.ts (1)
CommonGroupsOptions(7-19)types/common-partition-options.ts (1)
CommonPartitionOptions(3-15)types/common-options.ts (1)
CommonOptions(23-73)
rules/sort-maps/types.ts (3)
types/common-groups-options.ts (1)
CommonGroupsOptions(7-19)types/common-partition-options.ts (1)
CommonPartitionOptions(3-15)types/common-options.ts (1)
CommonOptions(23-73)
rules/sort-decorators/types.ts (5)
types/common-groups-options.ts (1)
CommonGroupsOptions(7-19)types/common-partition-options.ts (1)
CommonPartitionOptions(3-15)types/common-options.ts (2)
CommonOptions(23-73)RegexOption(464-464)types/sorting-node.ts (1)
SortingNode(18-102)utils/common-json-schemas.ts (1)
regexJsonSchema(242-251)
rules/sort-imports/types.ts (4)
types/common-options.ts (2)
RegexOption(464-464)CommonOptions(23-73)types/common-groups-options.ts (1)
CommonGroupsOptions(7-19)types/common-partition-options.ts (1)
CommonPartitionOptions(3-15)utils/sort-nodes-by-dependencies.ts (1)
SortingNodeWithDependencies(16-21)
rules/sort-array-includes/types.ts (3)
types/common-groups-options.ts (1)
CommonGroupsOptions(7-19)types/common-partition-options.ts (1)
CommonPartitionOptions(3-15)types/common-options.ts (1)
CommonOptions(23-73)
rules/sort-import-attributes/types.ts (6)
rules/sort-export-attributes/types.ts (4)
SingleCustomGroup(16-25)Group(32-32)singleCustomGroupJsonSchema(35-38)Options(40-44)types/common-options.ts (2)
RegexOption(464-464)CommonOptions(23-73)utils/common-json-schemas.ts (1)
regexJsonSchema(242-251)types/common-groups-options.ts (1)
CommonGroupsOptions(7-19)types/common-partition-options.ts (1)
CommonPartitionOptions(3-15)types/sorting-node.ts (1)
SortingNode(18-102)
rules/sort-export-attributes.ts (17)
utils/create-eslint-rule.ts (1)
createEslintRule(32-35)utils/is-sortable.ts (1)
isSortable(7-9)utils/get-settings.ts (1)
getSettings(62-107)utils/complete.ts (1)
complete(30-45)utils/validate-custom-sort-configuration.ts (1)
validateCustomSortConfiguration(29-37)utils/validate-generated-groups-configuration.ts (1)
validateGeneratedGroupsConfiguration(75-93)utils/validate-newlines-and-partition-configuration.ts (1)
validateNewlinesAndPartitionConfiguration(98-119)utils/get-eslint-disabled-lines.ts (1)
getEslintDisabledLines(45-97)utils/compute-group.ts (1)
computeGroup(77-115)utils/does-custom-group-match.ts (1)
doesCustomGroupMatch(121-141)utils/is-node-eslint-disabled.ts (1)
isNodeEslintDisabled(27-32)utils/range-to-diff.ts (1)
rangeToDiff(32-41)utils/should-partition.ts (1)
shouldPartition(69-95)utils/sort-nodes-by-groups.ts (1)
sortNodesByGroups(106-162)utils/get-custom-groups-compare-options.ts (1)
buildGetCustomGroupOverriddenOptionsFunction(131-142)utils/report-all-errors.ts (1)
reportAllErrors(203-325)utils/report-errors.ts (4)
MISSED_SPACING_ERROR(33-34)EXTRA_SPACING_ERROR(30-31)GROUP_ORDER_ERROR(27-28)ORDER_ERROR(21-22)
rules/sort-named-exports/types.ts (5)
rules/sort-named-imports/types.ts (2)
Options(47-59)SingleCustomGroup(22-40)types/common-groups-options.ts (1)
CommonGroupsOptions(7-19)types/common-partition-options.ts (1)
CommonPartitionOptions(3-15)types/common-options.ts (1)
CommonOptions(23-73)types/sorting-node.ts (1)
SortingNode(18-102)
rules/sort-modules/types.ts (3)
types/common-groups-options.ts (1)
CommonGroupsOptions(7-19)types/common-partition-options.ts (1)
CommonPartitionOptions(3-15)types/common-options.ts (1)
CommonOptions(23-73)
rules/sort-object-types/types.ts (4)
types/common-options.ts (4)
RegexOption(464-464)CustomGroupsOption(103-134)FallbackSortOption(301-313)CommonOptions(23-73)types/common-groups-options.ts (1)
CommonGroupsOptions(7-19)types/common-partition-options.ts (1)
CommonPartitionOptions(3-15)types/join-with-dash.ts (1)
JoinWithDash(4-4)
rules/sort-objects/types.ts (3)
types/common-options.ts (2)
RegexOption(464-464)CommonOptions(23-73)types/common-groups-options.ts (1)
CommonGroupsOptions(7-19)types/common-partition-options.ts (1)
CommonPartitionOptions(3-15)
rules/sort-classes/types.ts (3)
types/common-options.ts (2)
RegexOption(464-464)CommonOptions(23-73)types/common-groups-options.ts (1)
CommonGroupsOptions(7-19)types/common-partition-options.ts (1)
CommonPartitionOptions(3-15)
rules/sort-union-types/types.ts (3)
types/common-groups-options.ts (1)
CommonGroupsOptions(7-19)types/common-partition-options.ts (1)
CommonPartitionOptions(3-15)types/common-options.ts (1)
CommonOptions(23-73)
rules/sort-variable-declarations/types.ts (3)
types/common-groups-options.ts (1)
CommonGroupsOptions(7-19)types/common-partition-options.ts (1)
CommonPartitionOptions(3-15)types/common-options.ts (1)
CommonOptions(23-73)
rules/sort-exports/types.ts (3)
types/common-groups-options.ts (1)
CommonGroupsOptions(7-19)types/common-partition-options.ts (1)
CommonPartitionOptions(3-15)types/common-options.ts (1)
CommonOptions(23-73)
rules/sort-jsx-props/types.ts (4)
rules/sort-array-includes/types.ts (2)
Options(19-35)SingleCustomGroup(49-61)types/common-options.ts (2)
RegexOption(464-464)CommonOptions(23-73)types/common-partition-options.ts (1)
CommonPartitionOptions(3-15)types/common-groups-options.ts (1)
CommonGroupsOptions(7-19)
rules/sort-named-imports/types.ts (4)
types/common-groups-options.ts (1)
CommonGroupsOptions(7-19)types/common-partition-options.ts (1)
CommonPartitionOptions(3-15)types/common-options.ts (1)
CommonOptions(23-73)types/sorting-node.ts (1)
SortingNode(18-102)
🔇 Additional comments (35)
rules/sort-variable-declarations/types.ts (2)
3-5: Imports of shared option types look correct and consistentBringing in
CommonPartitionOptions,CommonOptions,RegexOption, andCommonGroupsOptionsaligns this rule with the shared option abstractions used elsewhere; the types line up with their definitions and are appropriate for the new compositeOptionstype.
31-41: The implementation is correct; suggested refactoring conflicts with codebase patternsThe array-based
Optionstype is correctly implemented throughout: tests useoptions: [{}], the rule accesses it viacontext.options.at(0), anddefaultOptionsis properly typed asRequired<Options[number]>. No remaining assumptions of a single options object exist.However, the review's suggestions conflict with established codebase patterns:
allSelectorsasconst: All other rules in the codebase (sort-object-types, sort-union-types, sort-named-imports, sort-objects, sort-modules, sort-named-exports) useexport let allSelectors, notconst. Changing this would introduce inconsistency.- Named alias extraction: While cosmetic and clean, this is optional and not required for correctness or readability—the inline intersection is transparent and mirrors the inline structure already present in other shared option types.
docs/content/rules/sort-jsx-props.mdx (4)
318-330: Groups/newlines option docs now match the newgroupssurface.The updated
groupsunion (string, string[],{ newlinesBetween }, and{ group, type?, order? }) plus the dedicated “Newlines between groups” section correctly describe per‑group overrides and boundary newlines behavior, in line with the sharedCommonGroupsOptionsdesign. No issues here.Also applies to: 373-390
488-502: Callback custom group example is clear and matches the newcustomGroupsAPI.The example correctly shows adding
'callback'togroupsand defining a matchingcustomGroupsentry withgroupName: 'callback'andelementNamePattern: '^on.+'; this is a good, realistic illustration of per‑group customization.
532-533: DefaultcustomGroupsupdated to array form.Switching the usage examples from
customGroups: {}tocustomGroups: []aligns the docs with the newArray<CustomGroupDefinition | CustomGroupAnyOfDefinition>API and the migration note above. This should avoid confusion for users copying the default config.Also applies to: 562-563
582-584: Updated test source link looks consistent with repo layout.The “Test source” link now points at
test/rules/sort-jsx-props.test.ts, which matches the rest of the project’s test references; as long as the Vitest migration kept this path, the link is correct.rules/sort-jsx-props/types.ts (1)
3-5: Options/Group wiring now consistently uses shared Common types.*The refactored
Optionstype (conditionaluseConfigurationIf,Pick<CommonPartitionOptions, 'partitionByNewLine'>,CommonGroupsOptions<Group, SingleCustomGroup>, andCommonOptions) plus the simplifiedGroupalias andallSelectors = ['prop']match the shared pattern used by other sorting rules and the public docs. The type surface looks coherent and type-safe for the rule’s configuration.Also applies to: 54-82, 108-108, 123-123
docs/content/rules/sort-maps.mdx (2)
276-288: Groups option type and per‑group overrides docs look consistent with new APIThe expanded
groupsunion type and the “Group with overridden settings” section accurately describe the array/override semantics (string, string[],{ newlinesBetween }, and{ group, type, order }) and match the CommonGroupsOptions shape used in code. This should give users enough detail to configure per‑group sort behavior and unsorted groups.Also applies to: 302-316
475-475: Updated test link pathThe
Test sourcelink now points attest/rules/sort-maps.test.ts, which matches the new test layout used elsewhere in the PR.rules/sort-array-includes/types.ts (1)
3-5: Options refactor to shared Common option blocks looks sound*Composing
OptionsfromCommonGroupsOptions<Group, SingleCustomGroup>,CommonPartitionOptions, andCommonOptions(plus the rule‑specificuseConfigurationIf) is consistent with the new shared option model across rules and should keep this rule aligned with the common JSON‑schema/typing story. TheGroup = 'unknown' | stringalias remains compatible withCommonGroupsOptions’Group extends stringconstraint, andRegexOptionis correctly reused forallNamesMatchPattern.Please run the TypeScript build or type‑check to ensure all downstream imports of
Optionsand the JSON‑schema builder for this rule still type‑check cleanly with the new composition.Also applies to: 32-34
docs/content/rules/sort-variable-declarations.mdx (3)
219-231: Groups union and per‑group override docs align with shared groups APIThe updated
groupstype union and the “Group with overridden settings” section correctly mirror the new CommonGroupsOptions shape (string, string[],{ newlinesBetween }, and{ group, type?, order? }). The example using'initialized'and{ group: 'uninitialized', type: 'unsorted' }clearly shows how to disable sorting for a specific group while preserving global behavior elsewhere.Also applies to: 252-266
294-294: Clarified customGroups descriptionThe change to “match specific variable declaration members” better reflects this rule’s domain and avoids confusion with object‑type members.
426-426: Test link path updatePointing the
Test sourcelink totest/rules/sort-variable-declarations.test.tsmatches the reorganized test tree and keeps docs in sync with the repository.rules/sort-maps/types.ts (1)
3-5: Options composition matches shared configuration modelRefactoring
Optionsto bePartial<{ useConfigurationIf: ... } & CommonGroupsOptions<Group, SingleCustomGroup> & CommonPartitionOptions & CommonOptions>[]cleanly aligns this rule with the shared option blocks used elsewhere. The dedicatedSingleCustomGroupinterface andsingleCustomGroupJsonSchemaforelementNamePatternmatch the documented customGroups shape for maps, andRegexOptionis reused appropriately forallNamesMatchPattern.It would be good to re‑run the type‑checker and ensure the JSON‑schema builder and rule implementation for
sort-maps(especially whereOptions[number]is used) still compile against this updated type.Also applies to: 28-30
docs/content/rules/sort-object-types.mdx (5)
287-289: New useConfigurationIf filters are well documentedAdding
declarationCommentMatchesPatternandhasNumericKeysOnlytouseConfigurationIfand documenting their behavior (including the limitation to unquoted numeric literal keys) gives users fine‑grained control over when configurations apply. The examples fordeclarationCommentMatchesPattern: '^do not sort$'andhasNumericKeysOnly: trueclearly demonstrate realistic use cases.Also applies to: 352-376, 378-393
307-320: RGB customGroups example matches the new array-based APIThe updated
customGroupsexample using an array of{ groupName, elementNamePattern }objects is consistent with the new array‑basedcustomGroupsoption and clearly shows how to mapr,g, andbkeys into dedicated groups alongside thegroups: ['r', 'g', 'b']configuration.
398-410: Groups union and per‑group overrides section align with shared groups semanticsThe expanded
groupstype union and accompanying examples (“Group with overridden settings”) correctly describe the supported entries (selectors as strings, combined groups as string[],{ newlinesBetween }separators, and{ group, type?, order? }overrides). The example that makesmultiline-memberunsorted illustrates the override behavior well and is consistent with how other rules’ docs now present group‑level overrides.Also applies to: 444-453, 524-538
678-696: Combined groups and customGroups “top/unknown/bottom” example is clearThe configuration showing
groups: ['top', 'unknown', ['optional-multiline-member', 'bottom']]plus matchingcustomGroupsfortopandbottomnicely demonstrates combining multiple groups and driving them via selector/pattern‑based custom groups. This should help users reason about more advanced grouping setups.
784-784: Test link path in Resources updated correctlyLinking to
test/rules/sort-object-types.test.tsmatches the new test file layout and keeps the documentation’s “Test source” reference accurate.rules/sort-union-types/types.ts (1)
3-5: Options refactor cleanly composes shared Common option types*The new imports and
Optionsalias (Partial<CommonGroupsOptions<Group, SingleCustomGroup> & CommonPartitionOptions & CommonOptions>[]) look correct and consistent with other rules; no issues from a type-soundness or API-shape perspective.Also applies to: 51-60
rules/sort-named-exports/types.ts (1)
4-6: Named-exports Options and sorting-node alias look consistent with the new shared patternThe Options refactor (array of
Partial<{ ignoreAlias } & CommonGroupsOptions<Group, SingleCustomGroup> & CommonPartitionOptions & CommonOptions>) and theSortNamedExportsSortingNode = SortingNode<TSESTree.ExportSpecifier>alias both look coherent and in line with the other sorting rules’ API shapes. Please just ensure the rule implementation and tests now operate onExportSpecifiernodes rather than the previous declaration-level shape.Also applies to: 43-59, 61-62
rules/sort-classes/types.ts (1)
3-5: SortClassesOptions now cleanly composes shared Common options*The updated
SortClassesOptionstuple, intersecting{ ignoreCallbackDependenciesPatterns }withCommonGroupsOptions<Group, SingleCustomGroup>,CommonPartitionOptions, andCommonOptions, is type-sound and matches the shared configuration model adopted elsewhere; no changes needed.Also applies to: 32-51
rules/sort-named-imports/types.ts (1)
4-6: Named-imports Options and sorting-node alias are aligned with the shared config modelThe new
Optionsalias (array ofPartial<{ ignoreAlias } & CommonGroupsOptions<Group, SingleCustomGroup> & CommonPartitionOptions & CommonOptions>) andSortNamedImportsSortingNode = SortingNode<TSESTree.ImportClause>look correct and consistent with other rules. Please confirm the rule implementation and tests are updated to work withImportClause-based sorting nodes.Also applies to: 42-59, 61-62
rules/sort-object-types/types.ts (1)
10-11: Options refactor for sort-object-types correctly specializes Common options*The
Optionstype now cleanly combines rule-specific fields (useConfigurationIf, specializedcustomGroups, specializedfallbackSort,sortBy) with shared behavior by intersectingOmit<CommonGroupsOptions<Group, SingleCustomGroup>, 'customGroups'>,Omit<CommonOptions, 'fallbackSort'>, andCommonPartitionOptions. The additionaldeclarationCommentMatchesPattern?andhasNumericKeysOnly?flags, plus the enrichedcustomGroups/fallbackSortshapes usingCustomGroupsOption<SingleCustomGroup, { fallbackSort?: { sortBy?: 'value' | 'name' } & FallbackSortOption }>, all look type-safe and aligned with the intended configuration semantics.Also applies to: 27-39, 52-67, 72-86
rules/sort-object-types/build-node-value-getter.ts (1)
15-23: LGTM! Enhanced exhaustiveness checking.The switch statement provides better compile-time type safety compared to a ternary. The UnreachableCaseError in the default case ensures exhaustive handling of all sortBy variants.
rules/sort-imports/types.ts (1)
181-185: LGTM! New modifiers properly integrated.The
singlelineandmultilinemodifiers are correctly defined and integrated into theallModifiersarray.docs/content/rules/sort-union-types.mdx (1)
235-247: LGTM! Well-documented per-group override feature.The expanded
groupstype definition clearly documents the new per-group override capabilities, allowing fine-grained control over sorting behavior for specific groups.docs/content/rules/sort-enums.mdx (1)
173-179: LGTM! Clear documentation of sortByValue options.The documentation correctly explains the three-value
sortByValueoption and its behavior for each setting.docs/content/rules/sort-named-exports.mdx (1)
253-265: LGTM! Consistent documentation structure.The groups option documentation follows the same clear pattern as other rules in this PR, making the codebase documentation more consistent.
docs/content/rules/sort-classes.mdx (1)
327-339: LGTM! Comprehensive groups option documentation.The updated type definition clearly shows all the flexible configuration options available for the groups array, including per-group overrides and newline control.
rules/sort-exports/types.ts (1)
3-6: Options type composition looks consistent with shared option infrastructureThe
Optionsalias cleanly composesCommonGroupsOptions<Group, SingleCustomGroup>,CommonPartitionOptions, andCommonOptionsand matches the patterns used in other rules. No issues from this file alone; it should integrate smoothly with the rule implementation.Please double-check that
rules/sort-exports.tstreatsOptionsconsistently (e.g., how it pullsOptions[0]vs. the options array) in the same way as other refactored sorting rules.Also applies to: 48-58
rules/sort-objects/types.ts (1)
3-5: NewOptions/ selector wiring for sort-objects looks coherentThe extended
Options(withuseConfigurationIffields and composition ofCommonGroupsOptions,CommonPartitionOptions, andCommonOptions) plus the updatedSelector/Group/allSelectorswiring all look internally consistent and compatible with the shared helpers.Please confirm that:
- The docs for
sort-objectslist the newuseConfigurationIffields (objectType,declarationCommentMatchesPattern,declarationMatchesPattern,hasNumericKeysOnly), and- The rule implementation applies them as intended.
Also applies to: 20-63, 78-81, 115-122, 205-205, 257-257
rules/sort-import-attributes/types.ts (1)
1-47: Types and schema look consistent with existing attribute rules.The
SingleCustomGroup,Group,Options, andsingleCustomGroupJsonSchemadefinitions align with the sharedCommon*option patterns and thesort-export-attributestypes, so the new rule surface looks coherent and type‑safe.rules/sort-modules/types.ts (1)
3-55: RefactoredSortModulesOptionscorrectly composes shared option types.Using
CommonGroupsOptions<Group, SingleCustomGroup> & CommonPartitionOptions & CommonOptionsinside the single‑element tuple keeps the ESLint[options]shape while aligning with the new common option model; this looks sound.test/rules/sort-array-includes.test.ts (1)
840-871: LGTM! Well-structured test for per-group option overrides.This test correctly validates the new per-group override feature, ensuring that group-specific
typeandordersettings override global configuration.
| { | ||
| type: 'unsorted', // Do not sort metadata objects | ||
| useConfigurationIf: { | ||
| declarationMatchesPattern: '*metadata$', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Clarify pattern syntax for declarationMatchesPattern.
The example shows declarationMatchesPattern: '*metadata$' which mixes glob-like (*) and regex-like ($) syntax. Based on the type definition on line 310 showing it accepts regex patterns, this should likely be '.*metadata$' or 'metadata$' to be valid regex.
Apply this diff if regex is intended:
- declarationMatchesPattern: '*metadata$',
+ declarationMatchesPattern: '.*metadata$',📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| declarationMatchesPattern: '*metadata$', | |
| declarationMatchesPattern: '.*metadata$', |
🤖 Prompt for AI Agents
In docs/content/rules/sort-objects.mdx around line 387, the example uses a mixed
glob/regex pattern `*metadata$` which is invalid for a regex-based field; update
the value to a valid regex such as `'.*metadata$'` (or `'metadata$'` if only
suffix match is desired) so it matches the intended metadata suffix and conforms
to the type definition.
| export type Options = Partial< | ||
| { | ||
| sortOnParameters: boolean | ||
| sortOnProperties: boolean | ||
| sortOnAccessors: boolean | ||
| sortOnMethods: boolean | ||
| sortOnClasses: boolean | ||
| } & CommonGroupsOptions<Group, SingleCustomGroup> & | ||
| CommonPartitionOptions & | ||
| CommonOptions | ||
| >[] | ||
|
|
||
| export interface SingleCustomGroup { | ||
| elementNamePattern?: RegexOption | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
SingleCustomGroup is missing groupName, which breaks typed customGroups and schema alignment.
Every other rule’s SingleCustomGroup (e.g. sort-export-attributes) exposes a groupName: string so that customGroups entries can be named and referenced from groups. Here it’s omitted from both the TypeScript interface and the singleCustomGroupJsonSchema, which means:
- TS configs using
customGroups: [{ groupName: 'myGroup', ... }]will fail excess‑property checks againstSingleCustomGroup. - The JSON schema won’t validate or even describe the
groupNamefield for this rule’s custom groups.
To align with the shared customGroups model and avoid surprising TS/schema behavior, consider:
export type Options = Partial<
{
sortOnParameters: boolean
sortOnProperties: boolean
sortOnAccessors: boolean
sortOnMethods: boolean
sortOnClasses: boolean
} & CommonGroupsOptions<Group, SingleCustomGroup> &
CommonPartitionOptions &
CommonOptions
>[]
export interface SingleCustomGroup {
- elementNamePattern?: RegexOption
+ /** Name of the custom group, referenced from the `groups` option. */
+ groupName: string
+
+ /** Pattern used to match decorator names for this custom group. */
+ elementNamePattern?: RegexOption
}
type Group = 'unknown' | string
export let singleCustomGroupJsonSchema: Record<string, JSONSchema4> = {
- elementNamePattern: regexJsonSchema,
+ groupName: { type: 'string' },
+ elementNamePattern: regexJsonSchema,
}This mirrors the other rules’ custom-group surfaces and keeps TS types and JSON schema consistent.
Also applies to: 31-33
🤖 Prompt for AI Agents
In rules/sort-decorators/types.ts around lines 11 to 25, the SingleCustomGroup
type lacks groupName which breaks typed customGroups and the JSON schema; add a
groupName: string field to the SingleCustomGroup interface and update the
corresponding singleCustomGroupJsonSchema to include a groupName property (type:
"string") and mark it required if other rules require it, and make the same
change where SingleCustomGroup is duplicated around lines 31-33 so TypeScript
types and schema align with other rules.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 5
♻️ Duplicate comments (8)
docs/content/rules/sort-heritage-clauses.mdx (1)
148-159: Fix terminology: replace "class decorators" with "heritage clauses".The existing comment flag from the prior review still applies here. This rule concerns
extends/implementsclauses, not decorators.- Enables the use of comments to separate class decorators into logical groups. + Enables the use of comments to separate heritage clauses into logical groups.docs/content/rules/sort-modules.mdx (1)
519-519: Fix syntax error: remove trailing periodsThe
elementNamePatternvalues have trailing periods, making the TypeScript code invalid.Apply this diff:
- elementNamePattern: 'Input'. + elementNamePattern: 'Input'Apply the same fix on both lines 519 and 523.
Also applies to: 523-523
test/rules/sort-export-attributes.test.ts (2)
25-25: Fix test title: "import" → "export"This test validates export attribute sorting, not import attributes.
50-50: Fix additional test titles: "import" → "export"These test descriptions incorrectly reference "import attributes" when they validate export attribute sorting.
Update the following lines:
- Line 50: "sorts multiline import attributes" → "sorts multiline export attributes"
- Line 323: "sorts import attributes" → "sorts export attributes"
- Line 348: "sorts multiline import attributes" → "sorts multiline export attributes"
- Line 598: "sorts import attributes" → "sorts export attributes"
- Line 623: "sorts multiline import attributes" → "sorts multiline export attributes"
- Line 878: "sorts import attributes using custom alphabet" → "sorts export attributes using custom alphabet"
Also applies to: 323-323, 348-348, 598-598, 623-623, 878-878
docs/content/rules/sort-objects.mdx (1)
387-387: Fix pattern syntax: use valid regexThe pattern
'*metadata$'mixes glob-like (*) and regex-like ($) syntax. For a regex pattern, use'.*metadata$'or'metadata$'.Apply this diff:
- declarationMatchesPattern: '*metadata$', + declarationMatchesPattern: '.*metadata$',docs/content/rules/sort-decorators.mdx (1)
382-389: Correct CustomGroupDefinition typings for consistencyThe
fallbackSort.typefield usesstringinstead of the proper union type used elsewhere in this file (lines 145-150). For consistency, use the same type union.Apply this diff:
interface CustomGroupDefinition { groupName: string type?: 'alphabetical' | 'natural' | 'line-length' | 'unsorted' order?: 'asc' | 'desc' - fallbackSort?: { type: string; order?: 'asc' | 'desc' } + fallbackSort?: { + type: 'alphabetical' | 'natural' | 'line-length' | 'custom' | 'unsorted' + order?: 'asc' | 'desc' + } newlinesInside?: number elementNamePattern?: string | string[] | { pattern: string; flags?: string } | { pattern: string; flags?: string }[] }Note: The past review also suggested changing
newlinesInsideto'always' | 'never' | number, but I cannot verify this is correct from the provided context. Verify against the actual type definitions.docs/content/rules/sort-jsx-props.mdx (1)
269-287: Fix the RGB regex anchoring in the example configuration
allNamesMatchPattern: '^r|g|b$'is parsed as(^r)orgor(b$), so it will also match names that merely containgor end withb. Wrap the alternatives in a single anchored group so only exact"r","g", or"b"match:- useConfigurationIf: { - allNamesMatchPattern: '^r|g|b$', - }, + useConfigurationIf: { + allNamesMatchPattern: '^(?:r|g|b)$', + },docs/content/rules/sort-interfaces.mdx (1)
539-547: Make the “Example 2” interface snippet syntactically completeThe
Interfaceexample ends withmethod(): stringbut never closes the interface before the code fence. This makes the sample invalid TypeScript and was already called out earlier. Consider adding the missing}:interface Interface { // 'index-signature' [key: string]: any; // 'optional-property' description?: string; // 'required-method' method(): string -``` +} +```
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (26)
docs/content/rules/sort-array-includes.mdx(5 hunks)docs/content/rules/sort-classes.mdx(4 hunks)docs/content/rules/sort-decorators.mdx(6 hunks)docs/content/rules/sort-enums.mdx(6 hunks)docs/content/rules/sort-export-attributes.mdx(1 hunks)docs/content/rules/sort-exports.mdx(4 hunks)docs/content/rules/sort-heritage-clauses.mdx(6 hunks)docs/content/rules/sort-import-attributes.mdx(1 hunks)docs/content/rules/sort-imports.mdx(6 hunks)docs/content/rules/sort-interfaces.mdx(8 hunks)docs/content/rules/sort-intersection-types.mdx(6 hunks)docs/content/rules/sort-jsx-props.mdx(7 hunks)docs/content/rules/sort-maps.mdx(3 hunks)docs/content/rules/sort-modules.mdx(4 hunks)docs/content/rules/sort-named-exports.mdx(3 hunks)docs/content/rules/sort-named-imports.mdx(3 hunks)docs/content/rules/sort-object-types.mdx(8 hunks)docs/content/rules/sort-objects.mdx(9 hunks)docs/content/rules/sort-sets.mdx(5 hunks)docs/content/rules/sort-union-types.mdx(5 hunks)docs/content/rules/sort-variable-declarations.mdx(4 hunks)test/rules/sort-array-includes.test.ts(42 hunks)test/rules/sort-classes.test.ts(27 hunks)test/rules/sort-decorators.test.ts(3 hunks)test/rules/sort-enums.test.ts(41 hunks)test/rules/sort-export-attributes.test.ts(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (6)
- docs/content/rules/sort-maps.mdx
- test/rules/sort-classes.test.ts
- docs/content/rules/sort-import-attributes.mdx
- docs/content/rules/sort-export-attributes.mdx
- docs/content/rules/sort-classes.mdx
- docs/content/rules/sort-intersection-types.mdx
🧰 Additional context used
🧬 Code graph analysis (1)
test/rules/sort-export-attributes.test.ts (2)
utils/alphabet.ts (1)
Alphabet(46-467)test/utils/validate-rule-json-schema.ts (1)
validateRuleJsonSchema(8-19)
🔇 Additional comments (31)
docs/content/rules/sort-named-imports.mdx (3)
252-265: LGTM!The expanded Groups type definition correctly documents the new per-group override capabilities.
299-314: LGTM!The "Group with overridden settings" section clearly documents the new per-group override feature.
476-476: LGTM!Test source link correctly updated to the new path.
docs/content/rules/sort-modules.mdx (1)
690-690: LGTM!Test source link correctly points to the new path structure.
docs/content/rules/sort-object-types.mdx (3)
287-289: LGTM!New
useConfigurationIfoptions are well-documented with clear examples.Also applies to: 352-393
398-411: LGTM!Groups type definition correctly reflects the expanded API with per-group overrides.
525-540: LGTM!Clear documentation of the per-group override feature.
docs/content/rules/sort-variable-declarations.mdx (2)
219-232: LGTM!Groups type and per-group overrides are well-documented and consistent with other rules.
Also applies to: 253-268
296-296: LGTM!Correctly updated terminology to match the rule's purpose (variable declarations, not object type members).
docs/content/rules/sort-objects.mdx (1)
463-476: LGTM!Groups type definition and per-group overrides are well-documented.
Also applies to: 565-580
docs/content/rules/sort-imports.mdx (2)
288-302: LGTM!Groups type definition, per-group overrides, and newlines between groups are thoroughly documented.
Also applies to: 454-495
362-363: LGTM!New
multilineandsinglelinemodifiers are properly documented.docs/content/rules/sort-decorators.mdx (2)
247-268: LGTM!New partitionByNewLine, newlinesBetween options, and per-group overrides are well-documented.
Also applies to: 273-286, 306-340
549-549: LGTM!Test source link correctly updated to the new path.
docs/content/rules/sort-union-types.mdx (1)
368-383: Documentation is clear and well-structured.The new "Group with overridden settings" section effectively explains per-group overrides for
type,order, andnewlinesInside. The example demonstrates the feature well.docs/content/rules/sort-enums.mdx (2)
173-179: sortByValue documentation is correct.The option is now properly documented as a string enum with three values ('always', 'never', 'ifNumericEnum') rather than a boolean, addressing the previous review feedback.
263-278: Group override documentation is clear and consistent.The "Group with overridden settings" section matches the pattern used in sort-union-types.mdx, maintaining consistency across rule documentation.
test/rules/sort-decorators.test.ts (3)
554-641: Excellent use of parameterized testing.The
it.eachapproach for testing differentelementNamePatternformats (string, array, case-insensitive regex, regex in array) is a best practice that reduces code duplication while ensuring comprehensive coverage.
935-1290: Comprehensive newline behavior testing.The extensive test coverage for
newlinesBetweenwith various values (0, 1, 'ignore') and their interactions with global vs. group-level settings ensures the complex newline logic is well-validated. The parameterized tests effectively cover the matrix of scenarios.
1334-1378: Good edge case coverage for partition boundaries.The test correctly verifies that partition boundaries are preserved even when
newlinesBetween: 0is set, which is an important edge case that could easily be overlooked.test/rules/sort-enums.test.ts (4)
70-74: Verify the intent behind numeric key quoting.The numeric enum keys have been changed from unquoted to single-quoted strings (e.g.,
'1','12','2','8'). This appears intentional and consistent across all test sections, but please confirm this aligns with how the rule now handles numeric enum keys.If this change reflects updated behavior in how enum keys are normalized or compared, consider documenting this in the rule's documentation or changelog.
Also applies to: 91-95, 100-103
652-656: LGTM: sortByValue API evolution is well-tested.The change from a boolean
sortByValueoption to a string union ('always'|'never'|'ifNumericEnum') improves API clarity and provides more granular control. The test coverage for all three values is comprehensive.Since this is a breaking change for v5.0.0, ensure it's clearly documented in the migration guide.
Also applies to: 658-674
775-820: LGTM: Per-group override test is comprehensive.The new test validates that group-level overrides (type, order, newlinesInside) work correctly, covering both sorting and spacing enforcement. This aligns well with the PR's objective to add per-group configuration capabilities.
1172-1295: LGTM: Comprehensive newlinesBetween test coverage.The new tests thoroughly validate the
newlinesBetweenoption behavior:
- Value
0removes all newlines between groups- Value
1enforces exactly one newline- Proper error messages for
extraSpacingBetweenEnumsMembersandmissedSpacingBetweenEnumsMembersThe migration from string values like
'always'to numeric values (1) improves API clarity.Also applies to: 1327-1343
docs/content/rules/sort-array-includes.mdx (2)
312-327: LGTM: groups option type expansion is well-documented.The expanded
groupstype definition provides comprehensive support for per-group configuration, including:
- Simple string/array grouping
- Per-group newline controls (
newlinesBetween)- Per-group sort overrides (
type,order,newlinesInside)The default change from
[]to['literal']is a sensible improvement that provides better out-of-the-box behavior.Ensure this default change is highlighted in the migration guide for v5.0.0.
346-362: LGTM: Clear documentation for per-group overrides.The new "Group with overridden settings" section provides clear, practical examples of how to use per-group configuration. The example showing
{ group: 'spread', type: 'unsorted' }effectively demonstrates the feature.docs/content/rules/sort-exports.mdx (2)
264-286: LGTM: commentAbove feature is well-documented.The
commentAbovefeature for sort-exports is clearly explained, including:
- Purpose: Enforce presence of specific comments above group top elements
- Auto-fixing: Automatically adds missing comments
- Auto-removal: Removes invalid auto-added comments
The documentation appropriately warns users about the auto-removal behavior.
288-305: LGTM: Newlines between groups documentation is clear.The "Newlines between groups" section effectively explains how to use
newlinesBetweenobjects within thegroupsarray to override the global setting between specific groups. The prerequisite note aboutpartitionByNewLineis helpful.docs/content/rules/sort-sets.mdx (2)
271-286: LGTM: Documentation is consistent and terminology is clear.The groups type definition and default value changes are consistent with other rules in the PR. The terminology has been appropriately updated to refer to "Set elements" rather than generic elements, improving clarity.
Also applies to: 302-303
305-320: LGTM: Per-group override documentation is consistent.The "Group with overridden settings" section follows the same clear pattern established in other rule documentation files. The example appropriately demonstrates how to disable sorting for the
spreadgroup.test/rules/sort-array-includes.test.ts (1)
1351-1411: New newline/group-override tests look internally consistentThe added cases around
newlinesBetween(global vs per-group overrides, including0,1,2, and'ignore') and partition preservation exercise the edge semantics well; inputs, outputs, and expectederrorspayloads all line up with the described behavior, and option shapes match the rule’s public API. No issues from a test-logic perspective.Also applies to: 1584-1637, 3124-3184, 3357-3410, 4878-4937, 5111-5164
| 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 }[] | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add 'custom' to type unions in CustomGroupDefinition and CustomGroupAnyOfDefinition.
The type option at line 194 (within the groups section) explicitly includes 'custom' as a valid type. However, both custom group definition interfaces are missing 'custom' from their type unions. This inconsistency creates confusion about which sorting types are actually supported in custom groups.
interface CustomGroupDefinition {
groupName: string
- type?: 'alphabetical' | 'natural' | 'line-length' | 'unsorted'
+ type?: 'alphabetical' | 'natural' | 'line-length' | 'custom' | 'unsorted'
order?: 'asc' | 'desc'
fallbackSort?: { type: string; order?: 'asc' | 'desc' }
newlinesInside?: number
elementNamePattern?: string | string[] | { pattern: string; flags?: string } | { pattern: string; flags?: string }[]
} interface CustomGroupAnyOfDefinition {
groupName: string
- type?: 'alphabetical' | 'natural' | 'line-length' | 'unsorted'
+ type?: 'alphabetical' | 'natural' | 'line-length' | 'custom' | 'unsorted'
order?: 'asc' | 'desc'
fallbackSort?: { type: string; order?: 'asc' | 'desc' }
newlinesInside?: number
anyOf: Array<{
selector?: string
elementNamePattern?: string | string[] | { pattern: string; flags?: string } | { pattern: string; flags?: string }[]
}>
}Also applies to: 310-320
🤖 Prompt for AI Agents
In docs/content/rules/sort-heritage-clauses.mdx around lines 295-302 (and
similarly around 310-320), the CustomGroupDefinition and
CustomGroupAnyOfDefinition interfaces list type unions that omit the 'custom'
option; update both interfaces to include 'custom' in their type unions so the
docs reflect that custom groups accept type: 'custom' (ensure the union string
list includes 'custom' alongside 'alphabetical' | 'natural' | 'line-length' |
'unsorted').
| groups: ['r', 'g', 'b'], // Sort colors types by RGB | ||
| customGroups: { | ||
| r: '^r$', | ||
| g: '^g$', | ||
| b: '^b$', | ||
| }, | ||
| customGroups: [ | ||
| { | ||
| groupName: 'r', | ||
| elementNamePattern: '^r$', | ||
| }, | ||
| { | ||
| groupName: 'g', | ||
| elementNamePattern: '^g$', | ||
| }, | ||
| { | ||
| groupName: 'b', | ||
| elementNamePattern: '^b$', | ||
| }, | ||
| ], | ||
| useConfigurationIf: { | ||
| allNamesMatchPattern: '^r|g|b$', | ||
| }, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Correct the RGB regex anchoring in this example
Here too, allNamesMatchPattern: '^r|g|b$' matches unintended names (g, words ending with b, etc.). To restrict it to interfaces whose keys are exactly "r", "g", or "b", wrap the alternation:
- useConfigurationIf: {
- allNamesMatchPattern: '^r|g|b$',
- },
+ useConfigurationIf: {
+ allNamesMatchPattern: '^(?:r|g|b)$',
+ },📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| groups: ['r', 'g', 'b'], // Sort colors types by RGB | |
| customGroups: { | |
| r: '^r$', | |
| g: '^g$', | |
| b: '^b$', | |
| }, | |
| customGroups: [ | |
| { | |
| groupName: 'r', | |
| elementNamePattern: '^r$', | |
| }, | |
| { | |
| groupName: 'g', | |
| elementNamePattern: '^g$', | |
| }, | |
| { | |
| groupName: 'b', | |
| elementNamePattern: '^b$', | |
| }, | |
| ], | |
| useConfigurationIf: { | |
| allNamesMatchPattern: '^r|g|b$', | |
| }, | |
| groups: ['r', 'g', 'b'], // Sort colors types by RGB | |
| customGroups: [ | |
| { | |
| groupName: 'r', | |
| elementNamePattern: '^r$', | |
| }, | |
| { | |
| groupName: 'g', | |
| elementNamePattern: '^g$', | |
| }, | |
| { | |
| groupName: 'b', | |
| elementNamePattern: '^b$', | |
| }, | |
| ], | |
| useConfigurationIf: { | |
| allNamesMatchPattern: '^(?:r|g|b)$', | |
| }, |
🤖 Prompt for AI Agents
In docs/content/rules/sort-interfaces.mdx around lines 330 to 347, the example
uses the regex allNamesMatchPattern: '^r|g|b$' which incorrectly anchors only
the first alternative and therefore matches unintended names; update the pattern
so the alternation is grouped and the anchors apply to the whole expression (for
example use '^(?:r|g|b)$' or '^(r|g|b)$') so only exact keys "r", "g", or "b"
match.
| <sub> | ||
| type: `Array<string | string[]>` | ||
| type: | ||
| ```ts | ||
| Array< | ||
| | string | ||
| | string[] | ||
| | { newlinesBetween: number } | ||
| | { | ||
| group: string | string[]; | ||
| type?: 'alphabetical' | 'natural' | 'line-length' | 'custom' | 'unsorted'; | ||
| order?: 'asc' | 'desc'; | ||
| newlinesInside?: number; | ||
| } | ||
| > | ||
| ``` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Align groups’ newlinesBetween override type with the global option
The groups type only documents { newlinesBetween: number }, while the global newlinesBetween option supports number | 'ignore'. If group-level newlinesBetween accepts the same values (as it appears to across the sorting rules), it would be clearer to document that here as well so consumers don’t assume numbers are the only valid overrides.
Also applies to: 566-583
🤖 Prompt for AI Agents
In docs/content/rules/sort-interfaces.mdx around lines 421-435 (also apply same
change for lines 566-583), the group-level type for newlinesBetween is
documented as only `{ newlinesBetween: number }` but the global option allows
`number | 'ignore'`; update the docblocks and code examples to accept `{
newlinesBetween: number | 'ignore' }` (and any array/union variants where group
overrides appear) so group-level newlinesBetween matches the global option;
ensure both occurrences at the two ranges are updated consistently.
| type: | ||
| ```ts | ||
| Array< | ||
| | string | ||
| | string[] | ||
| | { newlinesBetween: number } | ||
| | { | ||
| group: string | string[]; | ||
| type?: 'alphabetical' | 'natural' | 'line-length' | 'custom' | 'unsorted'; | ||
| order?: 'asc' | 'desc'; | ||
| newlinesInside?: number; | ||
| } | ||
| > | ||
| ``` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Document per-group newlinesBetween as accepting all supported values
The groups type currently documents { newlinesBetween: number }, but the global newlinesBetween option supports both numbers and 'ignore'. If group-level overrides are meant to mirror the same value space (as suggested by tests in other rules), consider updating the type and examples here to reflect number | 'ignore' so docs accurately describe the full API.
Also applies to: 375-392
🤖 Prompt for AI Agents
In docs/content/rules/sort-jsx-props.mdx around lines 318-331 (and similarly
update the section at lines 375-392), the per-group option is documented as `{
newlinesBetween: number }` but should accept the same values as the global
`newlinesBetween` (number | 'ignore'); update the type annotation and any
examples to `{ newlinesBetween: number | 'ignore' }` and adjust example usages
to include the 'ignore' variant where appropriate so the docs match the actual
API and tests.
| type: | ||
| ```ts | ||
| Array< | ||
| | string | ||
| | string[] | ||
| | { newlinesBetween: number } | ||
| | { | ||
| group: string | string[]; | ||
| type?: 'alphabetical' | 'natural' | 'line-length' | 'custom' | 'unsorted'; | ||
| order?: 'asc' | 'desc'; | ||
| newlinesInside?: number; | ||
| } | ||
| > | ||
| ``` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Clarify allowable values for per-group newlinesBetween overrides
The groups union documents { newlinesBetween: number }, but the top-level newlinesBetween option accepts number | 'ignore'. If { newlinesBetween: 'ignore' } is valid between specific groups (to match that behavior), it would be good to reflect this in the type snippet and surrounding text so users understand all supported override values.
Also applies to: 317-334
🤖 Prompt for AI Agents
In docs/content/rules/sort-named-exports.mdx around lines 253 to 266 (and
likewise update the similar block at 317-334), the per-group override union
shows `{ newlinesBetween: number }` but the top-level option allows `number |
'ignore'`; update the type snippet and adjacent explanatory text so per-group
overrides accept `newlinesBetween: number | 'ignore'` (or `{ newlinesBetween:
number | 'ignore' }`) and mention that `'ignore'` is valid for per-group
settings to match top-level behavior.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml,!pnpm-lock.yaml
📒 Files selected for processing (1)
package.json(3 hunks)
🔇 Additional comments (1)
package.json (1)
14-14: ESM migration and dependency consolidation look solid.The transition to ESM (
"type": "module"), Node.js ≥20 requirement, and unified@typescript-eslint/*package versions at^8.47.0are all correctly aligned with the v5.0.0 release objectives. The previous duplicate@typescript-eslint/typesissue has been resolved.Also applies to: 60-60, 83-84, 137-137
| "vitest": "^3.2.4" | ||
| }, | ||
| "peerDependencies": { | ||
| "eslint": ">=8.45.0" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Update ESLint peerDependency to v9+ to align with v5.0.0 release.
The PR objectives explicitly state "Drop legacy ESLint v8 support" (EOL September 2024), but the peerDependencies constraint still permits ESLint v8 (>=8.45.0). For a major version bump to v5.0.0, the package should require ESLint v9+ to enforce the breaking change.
Apply this diff to align the constraint with the v5.0.0 release goals:
- "eslint": ">=8.45.0"
+ "eslint": ">=9.0.0"📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| "eslint": ">=8.45.0" | |
| "eslint": ">=9.0.0" |
🤖 Prompt for AI Agents
In package.json at line 134, the peerDependency for "eslint" still allows v8
(">=8.45.0") but the v5.0.0 release drops ESLint v8 support; update the
constraint to require ESLint v9 or higher (e.g., ">=9.0.0" or a semver range
that enforces major version 9+) so the peerDependencies reflect the breaking
change.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (2)
astro.config.ts (2)
59-59: Static-analysis ReDoS warning is a false positive here; optional simplificationThe
new RegExp(\^${site}/guide$`, 'u')pattern is built from a constantsite` string and results in a simple anchored literal, so there’s no realistic ReDoS or injection risk despite the warning. If you want to make this clearer (and a bit cheaper), you could replace the regex with direct equality:filter: page => page !== `${site}/guide`,This keeps the same behavior without dynamic regex construction.
73-75:prefetch.defaultStrategy: 'hover'is conservative; consider touch behaviorUsing
prefetch: { defaultStrategy: 'hover' }reduces unnecessary prefetching and is good for network friendliness, but on touch‑only devices hover often doesn’t fire, so those users may see fewer prefetched navigations than before. If you want similar behavior on touch, you might considertaporviewportinstead; if not, this is fine as‑is.
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
astro.config.ts(2 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
astro.config.ts (1)
docs/utils/shiki-theme.ts (1)
colorTheme(3-8)
🪛 ast-grep (0.40.0)
astro.config.ts
[warning] 59-59: Regular expression constructed from variable input detected. This can lead to Regular Expression Denial of Service (ReDoS) attacks if the variable contains malicious patterns. Use libraries like 'recheck' to validate regex safety or use static patterns.
Context: new RegExp(^${site}/guide$, 'u')
Note: [CWE-1333] Inefficient Regular Expression Complexity [REFERENCES]
- https://owasp.org/www-community/attacks/Regular_expression_Denial_of_Service_-_ReDoS
- https://cwe.mitre.org/data/definitions/1333.html
(regexp-from-variable)
🔇 Additional comments (3)
astro.config.ts (3)
31-38: Shiki config reactivation and shared theme usage look goodRe‑enabling
markdown.shikiConfigwithtransformerNotationDiff({ matchAlgorithm: 'v3' })and the sharedcolorThemeis consistent and should give you diff highlighting with your custom CSS‑variable theme. No issues from my side here.
58-58: Switch to baresvelte()removes previous custom compiler optionsUsing plain
svelte()simplifies the integration and aligns with the default config for@astrojs/svelte, but it does drop the prior explicitcompilerOptions(e.g., customcssHash,discloseVersion). Just ensure you’re not relying on the old hashing or version‑disclosure behavior in snapshots or styling before merging.
70-70: Enablingexperimental.svgomay affect SVG markup shapeTurning on
experimental.svgo: trueis a nice optimization, but it can change SVG output (ID mangling, attribute ordering, whitespace), which in turn can affect HTML/SVG snapshots or very strict DOM assertions in tests. Worth double‑checking snapshot suites for SVG-heavy pages after this change.
|
@coderabbitai pause |
✅ Actions performedReviews paused. |
Close #566.