Skip to content

Conversation

azat-io
Copy link
Owner

@azat-io azat-io commented Oct 18, 2025

Description

A new rule for sorting regular expressions is added. It works with:

  • capture groups (/(error|warning|info|debug)/)
  • character classes (/[zxa-f0-9A-Z]/)
  • flags (/pattern/igmus)

Additional context

...

TODO:

At the moment the rule blindly reorders alternatives (e.g. (ab|a) becomes (a|ab)), which changes the behaviour of the regular expression.

const input = 'ab'

console.log(input.match(/(ab|a)/)?.[0]) // 'ab'
console.log(input.match(/(a|ab)/)?.[0])  // 'a'

We need to detect when alternatives share the same prefix and, in that case, avoid reporting an error or applying a fix.


What is the purpose of this pull request?

  • Bug fix
  • New Feature
  • Documentation update
  • Other

Before submitting the PR, please make sure you do the following

  • Check that there isn't already a PR that solves the problem the same way to avoid creating a duplicate.
  • Provide a description in this PR that addresses what the PR is solving, or reference the issue that it solves.
  • Ideally, include relevant tests that fail without this PR but pass with it.
  • Read contribution guidelines.

Copy link

coderabbitai bot commented Oct 18, 2025

📝 Walkthrough

Summary by CodeRabbit

  • New Features

    • Added sort-regexp ESLint rule to enforce consistent ordering of regular expression flags, character-class elements, and alternation branches.
    • Supports multiple sorting strategies including alphabetical, natural, line-length, and custom configurations.
  • Documentation

    • Added comprehensive documentation for the sort-regexp rule with configuration options, examples, and usage guides.
    • Updated rules index and public documentation references.

Walkthrough

This pull request introduces a new ESLint rule sort-regexp that enforces consistent ordering within regular expressions, including flags, character-class elements, and alternation branches. The addition encompasses rule implementation, type definitions, comprehensive test coverage, and full documentation updates.

Changes

Cohort / File(s) Summary
Documentation
docs/content/rules/sort-regexp.mdx, docs/public/llms.txt, readme.md
Adds documentation pages, LLM index entry, and readme table entry for the new sort-regexp rule with configuration options, examples, and feature description.
Rule Implementation
rules/sort-regexp.ts, rules/sort-regexp/types.ts
Implements the sort-regexp ESLint rule with two-phase sorting (flags, then alternatives/character classes), support for multiple sorting strategies (alphabetical, natural, line-length), custom grouping, and comprehensive configuration options via types module.
Plugin Registration
index.ts
Registers the sort-regexp rule by importing the rule module and adding it to the plugin's exported rules map and PluginConfig interface.
Dependencies
package.json
Adds @eslint-community/regexpp (^4.12.1) as a runtime dependency for regex parsing.
Test Suite
test/rules/sort-regexp.test.ts
Adds comprehensive test suite covering multiple sorting modes, edge cases (flags, character classes, alternatives, backreferences, lookaheads), custom groupings, and schema validation.

Sequence Diagram(s)

sequenceDiagram
    participant ESLint as ESLint Core
    participant Rule as sort-regexp Rule
    participant Parser as RegExp Parser
    participant Sorter as Sorting Logic

    ESLint->>Rule: onProgram (context)
    activate Rule
    
    Rule->>Rule: Register RegExp visitor
    
    ESLint->>Rule: Encounter RegExp Literal
    activate Rule
    
    Rule->>Parser: Parse RegExp pattern & flags
    activate Parser
    Parser-->>Rule: AST (flags, alternatives, char classes)
    deactivate Parser
    
    alt Phase 1: Flag Sorting
        Rule->>Sorter: Sort inline flags
        activate Sorter
        Sorter-->>Rule: Reordered flags + fix
        deactivate Sorter
        Rule->>Rule: Report if out of order
    end
    
    alt Phase 2: Content Sorting
        Rule->>Sorter: Analyze alternatives/char classes
        activate Sorter
        Sorter->>Sorter: Apply grouping (custom/alias)
        Sorter->>Sorter: Sort by strategy (alphabetical/natural/line-length)
        Sorter-->>Rule: Sorted elements + mappings
        deactivate Sorter
        Rule->>Rule: Report mismatches with fixes
    end
    
    deactivate Rule
    deactivate Rule
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

The changes span multiple files with heterogeneous purposes: configuration setup, comprehensive type definitions, substantial rule logic with multi-phase sorting and custom grouping support, and an extensive test suite. While documentation and setup files are straightforward, the core rule implementation (sort-regexp.ts) contains dense logic requiring careful review of sorting algorithms, group computation, and fix generation. The test suite is extensive and validates complex edge cases, warranting focused attention despite repetitive structure.

Pre-merge checks

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Title Check ✅ Passed The PR title "feat: add sort-regexp rule" is directly related to the primary objective of the changeset, which is adding a new ESLint rule for sorting regular expressions. The title follows a conventional commit format, is concise and clear, and provides specific information about what was added without vague terminology. A teammate scanning the repository history would understand that this commit introduces a new sorting rule for regular expressions.
Description Check ✅ Passed The PR description follows the template structure and includes all required sections. The Description section clearly explains what the PR solves by detailing that a new rule for sorting regular expressions is added and listing the supported features (capture groups, character classes, and flags). The Additional context section appropriately documents a known limitation with a concrete code example and identifies the TODO work needed to resolve it. The purpose checkbox correctly marks this as a "New Feature" and all four pre-submission checklist items are properly checked, indicating the author has followed the contribution guidelines.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@azat-io azat-io requested a review from Copilot October 18, 2025 16:23
Copy link

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

This pull request adds a new sort-regexp rule to the ESLint Perfectionist plugin that enforces consistent ordering in regular expressions. The rule sorts three main components: regex flags, character class elements, and alternation branches within capture groups or top-level patterns.

Key Changes:

  • New rule implementation that sorts regex flags, character classes, and alternation branches
  • Comprehensive test suite covering alphabetical, natural, line-length, custom, and unsorted sorting modes
  • Documentation and configuration updates to integrate the new rule

Reviewed Changes

Copilot reviewed 8 out of 9 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
rules/sort-regexp.ts Core rule implementation with sorting logic for regex components
rules/sort-regexp/types.ts Type definitions and configuration options for the rule
test/rules/sort-regexp.test.ts Extensive test suite covering all sorting modes and edge cases
docs/content/rules/sort-regexp.mdx Complete documentation with usage examples and configuration options
package.json Added regexpp dependency for regex AST parsing
index.ts Exported the new rule in the plugin's rule collection
Files not reviewed (1)
  • pnpm-lock.yaml: Language not supported

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

@@ -0,0 +1,2835 @@
/* Cspell:ignore gimsu igmus yusmig ysumgi Ωmega Δelta */
Copy link

Copilot AI Oct 18, 2025

Choose a reason for hiding this comment

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

Corrected spelling of 'gimsu' to 'gimus'

Suggested change
/* Cspell:ignore gimsu igmus yusmig ysumgi Ωmega Δelta */
/* Cspell:ignore gimus igmus yusmig ysumgi Ωmega Δelta */

Copilot uses AI. Check for mistakes.

Copy link
Owner Author

Choose a reason for hiding this comment

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

🤦

it('sorts character classes', async () => {
let customOptions = {
...options,
type: 'natural',
Copy link

Copilot AI Oct 18, 2025

Choose a reason for hiding this comment

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

The type property is redundant here since it's already defined in the options object being spread above.

Suggested change
type: 'natural',

Copilot uses AI. Check for mistakes.

Comment on lines +677 to +679
function codePointToString(value: number): string {
return String.fromCodePoint(value)
}
Copy link

Copilot AI Oct 18, 2025

Choose a reason for hiding this comment

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

This function is a simple wrapper around String.fromCodePoint. Consider using the native method directly or add JSDoc comments to explain why this abstraction is needed.

Copilot uses AI. Check for mistakes.

Copy link

codecov bot commented Oct 18, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 100.00%. Comparing base (a65b39e) to head (2109ae4).

Additional details and impacted files
@@            Coverage Diff             @@
##              next      #600    +/-   ##
==========================================
  Coverage   100.00%   100.00%            
==========================================
  Files          108       110     +2     
  Lines         8836      9379   +543     
  Branches      1695      1791    +96     
==========================================
+ Hits          8836      9379   +543     

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

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

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🧹 Nitpick comments (9)
rules/sort-regexp/types.ts (1)

64-75: Prefer const and literal types for exported constants

Use const (and literal typing) to prevent accidental mutation and improve type inference.

-export let allSelectors: Selector[] = ['alias', 'pattern']
+export const allSelectors = ['alias', 'pattern'] as const

-export let allModifiers: Modifier[] = []
+export const allModifiers: Modifier[] = []

-export let singleCustomGroupJsonSchema: Record<string, JSONSchema4> = {
+export const singleCustomGroupJsonSchema: Record<string, JSONSchema4> = {
   selector: buildCustomGroupSelectorJsonSchema(allSelectors as unknown as string[]),
   elementValuePattern: regexJsonSchema,
   elementNamePattern: regexJsonSchema,
 }
docs/content/rules/sort-regexp.mdx (1)

267-271: Avoid hardcoding release version until it ships

Package.json is 4.15.1 in this PR. Don’t claim v5.0.0 yet.

-## Version
-
-This rule was introduced in [v5.0.0](...).
+## Version
+
+Unreleased (will be included in the next major release). Update this section with the exact tag after publishing.
test/rules/sort-regexp.test.ts (2)

1182-1206: Add guard tests for non-commutative alternations and backrefs

To prevent unsafe fixes, add tests that must not report/fix when reordering could change behavior.

@@
   describe('alphabetical', () => {
@@
     it('works with complex cases', async () => {
@@
     })
+
+    it.skip('does not reorder shared-prefix alternatives (behavior would change)', async () => {
+      await valid({
+        // (ab|a) → (a|ab) would change which alternative matches
+        code: dedent`/(ab|a)/`,
+        options: [options],
+      })
+    })
+
+    it.skip('does not reorder when numeric backreferences depend on group order', async () => {
+      await valid({
+        // Reordering changes numbering of (b) vs (d), altering \2 semantics
+        code: dedent`/(?:c(d)|a(b))\\2/`,
+        options: [options],
+      })
+    })

Please un-skip once the rule detects and bails out for these cases.


2401-2468: Character class edge cases: ensure fix preserves literal “-” and “]”

Sorting must not turn literal “-” into a range or move “]” to an invalid position. Add tests to lock behavior.

@@
   describe('line-length', () => {
@@
     it('sorts character class elements', async () => {
@@
     })
+
+    it('preserves literal hyphen placement in character classes', async () => {
+      await valid({
+        code: dedent`/[-ab]/`, // '-' first is safe
+        options: [options],
+      })
+      await valid({
+        code: dedent`/[ab-]/`, // '-' last is safe
+        options: [options],
+      })
+      await valid({
+        code: dedent`/[a\\-b]/`, // escaped '-' is safe anywhere
+        options: [options],
+      })
+    })
+
+    it('does not produce invalid character classes with closing bracket', async () => {
+      await valid({
+        code: dedent`/[\\]ab]/`, // ']' escaped inside class
+        options: [options],
+      })
+    })

Run the suite to confirm the fixer never introduces invalid ranges or bracket placement.

rules/sort-regexp.ts (5)

243-248: Consider skipping character-class sorting under the /v flag until set-operations are handled.

ECMAScript’s /v introduces class set operations; naive reordering may change semantics. Either detect and skip when flags include 'v' or add targeted handling/tests.

Add a conservative guard:

         onCharacterClassLeave(characterClass) {
           let { elements, negate, start, end } = characterClass
+          if (literalNode.regex.flags.includes('v')) {
+            return
+          }
           if (!isSortable(elements)) {
             return
           }

Please add tests covering intersections/subtractions with /v.


376-379: Do not enable this rule in “recommended” until unsafe cases are blocked.

Given the behavior-changing edge cases above, ship as non‑recommended first. Flip to recommended after guards are in place and tests cover them.

-      recommended: true,
+      recommended: false,

641-649: Tighten the type guard or include lookarounds intentionally.

isCapturingContext never returns true for lookarounds but its predicate type includes LookaroundAssertion. Either add lookarounds to the check or narrow the return type.

 function isCapturingContext(
   node: Alternative['parent'],
-): node is LookaroundAssertion | CapturingGroup | Pattern | Group {
+): node is CapturingGroup | Pattern | Group {
   return (
     node.type === 'CapturingGroup' ||
     node.type === 'Group' ||
     node.type === 'Pattern'
   )
 }

178-242: Single-pass visitor for minor perf/readability win.

Both visitors traverse the same AST. Merge onAlternativeLeave and onCharacterClassLeave into a single visitRegExpAST call.

Also applies to: 243-348


375-386: Meta: keep fixers, but consider “suggest only” for alternatives until safe.

If you prefer not to flip recommended, make alternative reordering report-only (no fix) when ambiguity is detected; keep autofix for flags/character classes.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a65b39e and 2109ae4.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml, !pnpm-lock.yaml
📒 Files selected for processing (8)
  • docs/content/rules/sort-regexp.mdx (1 hunks)
  • docs/public/llms.txt (1 hunks)
  • index.ts (3 hunks)
  • package.json (1 hunks)
  • readme.md (1 hunks)
  • rules/sort-regexp.ts (1 hunks)
  • rules/sort-regexp/types.ts (1 hunks)
  • test/rules/sort-regexp.test.ts (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (3)
rules/sort-regexp.ts (19)
types/sorting-node.ts (1)
  • SortingNode (18-102)
rules/sort-regexp/types.ts (5)
  • Options (22-41)
  • allSelectors (65-65)
  • allModifiers (68-68)
  • Group (78-78)
  • Selector (59-59)
utils/create-eslint-rule.ts (1)
  • createEslintRule (32-35)
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/get-eslint-disabled-lines.ts (1)
  • getEslintDisabledLines (45-97)
utils/sort-nodes.ts (1)
  • sortNodes (39-76)
utils/create-node-index-map.ts (1)
  • createNodeIndexMap (27-35)
utils/pairwise.ts (1)
  • pairwise (29-44)
utils/sort-nodes-by-groups.ts (1)
  • sortNodesByGroups (106-162)
utils/report-all-errors.ts (1)
  • reportAllErrors (203-325)
utils/compare.ts (1)
  • compare (108-142)
utils/common-json-schemas.ts (3)
  • commonJsonSchemas (139-140)
  • buildCustomGroupsArrayJsonSchema (302-351)
  • groupsJsonSchema (165-190)
utils/report-errors.ts (1)
  • ORDER_ERROR (21-22)
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)
rules/sort-regexp/types.ts (2)
types/common-options.ts (4)
  • CustomGroupsOption (103-134)
  • GroupsOptions (427-433)
  • CommonOptions (23-73)
  • RegexOption (459-459)
utils/common-json-schemas.ts (2)
  • buildCustomGroupSelectorJsonSchema (431-439)
  • regexJsonSchema (219-228)
test/rules/sort-regexp.test.ts (2)
utils/alphabet.ts (1)
  • Alphabet (46-467)
test/utils/validate-rule-json-schema.ts (1)
  • validateRuleJsonSchema (8-19)
🪛 ESLint
test/rules/sort-regexp.test.ts

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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)


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

(typescript/no-unsafe-call)

🔇 Additional comments (5)
package.json (1)

60-63: Dependency addition LGTM

Adding @eslint-community/regexpp as a runtime dep matches the rule’s needs. No issues.

readme.md (1)

196-196: Rule table entry looks good

Entry formatting and link match existing rows.

docs/public/llms.txt (1)

47-47: Docs index update LGTM

Consistent with other entries.

index.ts (1)

23-50: Rule wiring is correct

Import, typing in PluginConfig, and rules map entry are consistent.

Also applies to: 97-98

rules/sort-regexp.ts (1)

1-68: Test coverage is comprehensive for standard patterns but missing edge cases for newer regex features.

The test file contains 156 test cases across 2835 lines and thoroughly covers:

  • Non-capturing groups and alternations
  • Character classes with ranges and special characters
  • All standard flags (i, g, m, s, u, y)
  • Complex nested patterns, lookahead/lookbehind assertions

However, the tests do not include:

  • The /v flag (Unicode Sets, ES2024)
  • Character class intersection/subtraction operators (&&, - at boundaries)
  • Character classes with dashes in boundary positions

The code structure (lines 1-68) is solid with proper imports and integration with shared utilities. Whether the missing edge case tests are acceptable depends on the project's scope and target environment compatibility. Verify if these features should be supported.

Comment on lines +22 to +23
The rule is **safe** – it only reorders elements without changing their meaning.

Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Docs overstate safety; add caveat and guidance

Reordering alternations is not universally safe (e.g., shared prefixes like (ab|a)), and numeric backreferences can also change behavior if group numbering shifts after reordering.

- The rule is **safe** – it only reorders elements without changing their meaning.
+ Important: Reordering can change behavior in specific cases (e.g., alternatives that share a prefix like `(ab|a)`, or patterns whose numeric backreferences depend on the textual order of capturing groups). The rule avoids such changes when it detects risk; otherwise, prefer `type: 'unsorted'` or disable the rule locally for those patterns.
📝 Committable suggestion

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

Suggested change
The rule is **safe**it only reorders elements without changing their meaning.
Important: Reordering can change behavior in specific cases (e.g., alternatives that share a prefix like `(ab|a)`, or patterns whose numeric backreferences depend on the textual order of capturing groups). The rule avoids such changes when it detects risk; otherwise, prefer `type: 'unsorted'` or disable the rule locally for those patterns.
🤖 Prompt for AI Agents
In docs/content/rules/sort-regexp.mdx around lines 22-23, the claim "The rule is
**safe** – it only reorders elements without changing their meaning." overstates
safety; update the text to add a short caveat and guidance: state that
reordering alternations can change behavior for patterns with shared prefixes
(e.g., (ab|a)) and when numeric capture group indices are relied upon by
backreferences, and advise when the rule is safe to apply (alternations are
independent, use non-capturing groups (?:...) or named captures to preserve
backreference semantics) and when to avoid it; include one minimal example of a
problematic case and a recommended fix or workaround (use non-capturing groups
or reorder/escape to preserve intended match) so readers know when to
enable/disable the rule.

Comment on lines +107 to +112
let eslintDisabledLines = getEslintDisabledLines({
ruleName: id,
sourceCode,
})

let ast = parseRegExpLiteral(literalNode.raw)
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Respect eslint-disable for the literal; bail out early.

Flags/character-class paths will still report even when the rule is disabled on that line. Add an early return after computing disabled lines.

       let eslintDisabledLines = getEslintDisabledLines({
         ruleName: id,
         sourceCode,
       })
 
+      // Skip this literal if the rule is disabled for its line
+      if (isNodeEslintDisabled(literalNode, eslintDisabledLines)) {
+        return
+      }

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In rules/sort-regexp.ts around lines 107 to 112, after computing
eslintDisabledLines with getEslintDisabledLines({ ruleName: id, sourceCode }),
add an early return that checks whether the regexp literal node's starting line
(literalNode.loc.start.line) is disabled for this rule and bail out if so; this
prevents further processing (like parseRegExpLiteral and subsequent
flag/character-class checks) when eslint-disable covers the literal's line.

Comment on lines +178 to +199
visitRegExpAST(ast, {
onAlternativeLeave(alternative) {
if (
!isCapturingContext(alternative.parent) ||
!isSortable(alternative.parent.alternatives)
) {
return
}

if (alternative !== alternative.parent.alternatives.at(-1)) {
return
}

let nodes = alternative.parent.alternatives.map(currentAlternative =>
createSortingNode({
alternative: currentAlternative,
eslintDisabledLines,
literalNode,
sourceCode,
options,
}),
)
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Avoid behavior-changing fixes when alternatives share a prefix.

Reordering (ab|a) to (a|ab) changes matches. Guard and skip reporting/fixing when any pair of alternatives is a prefix of another.

       visitRegExpAST(ast, {
         onAlternativeLeave(alternative) {
           if (
             !isCapturingContext(alternative.parent) ||
             !isSortable(alternative.parent.alternatives)
           ) {
             return
           }
 
           if (alternative !== alternative.parent.alternatives.at(-1)) {
             return
           }
 
+          // Safety: if any two alternatives share a prefix, skip to avoid behavior changes.
+          if (hasAmbiguousPrefixOrder(alternative.parent.alternatives)) {
+            return
+          }
+
           let nodes = alternative.parent.alternatives.map(currentAlternative =>
             createSortingNode({
               alternative: currentAlternative,
               eslintDisabledLines,
               literalNode,
               sourceCode,
               options,
             }),
           )

Add the helper:

+function hasAmbiguousPrefixOrder(alternatives: Alternative[]): boolean {
+  for (let i = 0; i < alternatives.length; i++) {
+    for (let j = i + 1; j < alternatives.length; j++) {
+      let a = alternatives[i]!.raw
+      let b = alternatives[j]!.raw
+      if (a.startsWith(b) || b.startsWith(a)) {
+        return true
+      }
+    }
+  }
+  return false
+}

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In rules/sort-regexp.ts around lines 178-199, the current fix can change regex
behavior when one alternative is a prefix of another (e.g. (ab|a) -> (a|ab)).
Before creating sorting nodes, add a guard that scans
alternative.parent.alternatives and, if any pair of alternatives has a prefix
relationship (one's source/raw startsWith the other's source/raw or vice versa),
skip reporting/fixing by returning early; implement a small helper like
isPrefixPair(a,b) that compares the alternatives' text and use it to detect any
prefix pair and bail out.

Comment on lines +254 to +306
let sortedElements = [...elements].toSorted((a, b) => {
let aKey = getCharacterClassElementSortKey(a)
let bKey = getCharacterClassElementSortKey(b)

if (
options.type !== 'line-length' &&
aKey.category !== bKey.category
) {
let categoryDiff = aKey.category - bKey.category
return options.order === 'asc' ? categoryDiff : -categoryDiff
}

let aNode = createCharacterClassSortingNode({
literalNode,
element: a,
})
let bNode = createCharacterClassSortingNode({
literalNode,
element: b,
})

let comparison = compare({
fallbackSortNodeValueGetter: null,
nodeValueGetter: null,
a: aNode,
b: bNode,
options,
})

if (comparison !== 0) {
return comparison
}

let rawComparison = aKey.raw.localeCompare(
bKey.raw,
options.locales,
{
sensitivity: options.ignoreCase ? 'base' : 'variant',
numeric: options.type === 'natural',
},
)

let rawOrderMultiplier = 1
if (options.type !== 'line-length' && options.order !== 'asc') {
rawOrderMultiplier = -1
}

return rawOrderMultiplier * rawComparison
})

let needsSort = elements.some(
(element, i) => element !== sortedElements[i],
)
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Prevent accidental ranges in character classes caused by bare '-'.

Sorting can move an unescaped '-' from edges into the middle, turning it into a range. Ensure bare '-' literals are kept at the end (or skip sorting).

-          let sortedElements = [...elements].toSorted((a, b) => {
+          let sortedElements = [...elements].toSorted((a, b) => {
             let aKey = getCharacterClassElementSortKey(a)
             let bKey = getCharacterClassElementSortKey(b)
             …
             return rawOrderMultiplier * rawComparison
           })
+
+          // Safety: keep any bare '-' (raw === '-') at the end to avoid creating unintended ranges.
+          if (sortedElements.some(el => el.type === 'Character' && el.raw === '-')) {
+            let hyphens: typeof sortedElements = []
+            let others: typeof sortedElements = []
+            for (let el of sortedElements) {
+              if (el.type === 'Character' && el.raw === '-') hyphens.push(el)
+              else others.push(el)
+            }
+            sortedElements = [...others, ...hyphens]
+          }
🤖 Prompt for AI Agents
In rules/sort-regexp.ts around lines 254 to 306, the current sort can move an
unescaped '-' literal from an edge into the middle of a character class,
creating an accidental range; modify the comparator so that bare (unescaped) '-'
elements are forced to the end of the sortedElements (or cause the function to
skip sorting when such a move would place '-' in the middle). Concretely: detect
an element that is a literal '-' and not escaped, and give it a sort priority
that always ranks it after all other elements (taking options.order into
account), or bail out of sorting for that character class when preserving edge
'-' placement cannot be guaranteed. Ensure this change only applies to unescaped
'-' and leaves other elements’ ordering logic intact.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant