Skip to content

feat(linter/eslint): implement prefer-named-capture-group rule#22759

Merged
camc314 merged 15 commits into
oxc-project:mainfrom
secustor:feat/add-prefer-named-capture-group
May 27, 2026
Merged

feat(linter/eslint): implement prefer-named-capture-group rule#22759
camc314 merged 15 commits into
oxc-project:mainfrom
secustor:feat/add-prefer-named-capture-group

Conversation

@secustor

@secustor secustor commented May 27, 2026

Copy link
Copy Markdown
Contributor

Disclaimer

  • The PR is mostly generated by ClaudeCode using Opus 4.7 and Sonnet 4.6
  • Every line has been reviewed by myself ( with negligible Rust experience )
  • Some adaptions have been done manually

Changes

Reimplements prefer-named-capture-group as linting rule.

There are two additional config options to prefer-named-capture-group:

  • allow_unnamed_groups ( defaults to 0): allows to set a lower bound of acceptable unnamed regex capture groups
  • additional_reg_exp_functions ( defaults to empty ): allows to set additional regex constructor considered. In Renovate's case we have an utility function which wraps regexes. The rule would fail to identify regexes supplied as string. e.g. regEx('(foo)(bar)')
    Inspired by
    allowed_names: FxHashSet<CompactStr>,

@secustor secustor requested a review from camc314 as a code owner May 27, 2026 11:41
@camc314 camc314 changed the title feat(rules): add support for 'prefer-named-capture-group' rule of eslint feat(linter/eslint): implement prefer-named-capture-group rule May 27, 2026
@camc314 camc314 self-assigned this May 27, 2026
@camc314 camc314 added the A-linter Area - Linter label May 27, 2026
@codspeed-hq

codspeed-hq Bot commented May 27, 2026

Copy link
Copy Markdown

Merging this PR will not alter performance

✅ 5 untouched benchmarks
⏩ 52 skipped benchmarks1


Comparing secustor:feat/add-prefer-named-capture-group (3c33110) with main (d9cb6d8)2

Open in CodSpeed

Footnotes

  1. 52 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

  2. No successful run was found on main (336ac7f) during the generation of this report, so d9cb6d8 was used instead as the comparison base. There might be some changes unrelated to this pull request in this report.

@camc314 camc314 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

thank you!

@camc314 camc314 merged commit fe93f97 into oxc-project:main May 27, 2026
28 checks passed

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR adds the ESLint prefer-named-capture-group rule to oxlint, wiring it into rule registration, generated configuration metadata, and tests/snapshots. The rule reports unnamed capturing groups in regex literals and RegExp constructor calls, including some statically resolvable concatenated/template patterns.

Changes:

  • Adds prefer_named_capture_group rule implementation and snapshot tests.
  • Extracts static_string_value into shared linter utilities and reuses it from unicorn/prefer_ternary.
  • Updates generated rule registries and configuration schema files.

Reviewed changes

Copilot reviewed 10 out of 12 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
crates/oxc_linter/src/rules/eslint/prefer_named_capture_group.rs Implements the new ESLint rule and tests.
crates/oxc_linter/src/snapshots/eslint_prefer_named_capture_group.snap Adds expected diagnostics snapshot for the new rule.
crates/oxc_linter/src/utils/static_value.rs Adds shared static string expression resolver.
crates/oxc_linter/src/utils/regex.rs Makes regex argument helper public.
crates/oxc_linter/src/utils/mod.rs Re-exports the new static value utility.
crates/oxc_linter/src/rules/unicorn/prefer_ternary.rs Reuses shared static string resolver.
crates/oxc_linter/src/rules.rs Registers the new rule module.
crates/oxc_linter/src/generated/rules_enum.rs Adds generated enum and metadata entries for the rule.
crates/oxc_linter/src/generated/rule_runner_impls.rs Adds generated rule runner implementation.
npm/oxlint/configuration_schema.json Adds the rule to generated npm config schema.
apps/oxlint/src-js/package/config.generated.ts Adds the rule to generated TypeScript config types.
tasks/website_linter/src/snapshots/schema_json.snap Updates website schema snapshot.

Comment on lines +99 to +114
let Some(pattern_expr) = arg0
.and_then(Argument::as_expression)
.map(Expression::get_inner_expression)
.filter(|expr| !is_directly_supported_regex_argument(expr))
else {
return;
};

let Some(pattern_text) = static_string_value(pattern_expr) else {
return;
};

let flags_text = arg1
.and_then(Argument::as_expression)
.map(Expression::get_inner_expression)
.and_then(static_string_value);
Comment on lines +31 to +34
#[derive(Debug, Default, Clone)]
pub struct PreferNamedCaptureGroup;

declare_oxc_lint!(
@secustor

Copy link
Copy Markdown
Contributor Author

Thanks for fixing up and merging!

@secustor secustor deleted the feat/add-prefer-named-capture-group branch May 27, 2026 14:21
camc314 pushed a commit that referenced this pull request Jun 1, 2026
# Oxlint
### 🚀 Features

- e4b1f46 linter/typescript: Implement `method-signature-style` rule
(#22679) (Mikhail Baev)
- bc462ca linter/vue: Implement no-reserved-component-names rule
(#22741) (bab)
- ef9e751 linter/vue: Implement component-definition-name-casing rule
(#22818) (bab)
- d67f51a linter/vue: Implement require-prop-type-constructor rule
(#22708) (bab)
- 1444f82 linter/promise/spec-only: Add `Promise.try` to `Promise`
static methods (#22812) (Ben Saufley)
- 8422e8b linter/jsdoc: Implement `require-yields-description` rule
(#22805) (Mikhail Baev)
- fe93f97 linter/eslint: Implement `prefer-named-capture-group` rule
(#22759) (Sebastian Poxhofer)
- 1a7798b linter: Add suggestion for `unicorn/no-new-array` (#22682)
(Sysix)

### 🐛 Bug Fixes

- 760a9f9 linter: Report errors when writing to the filesystem (#22881)
(camc314)
- e5a2748 linter: Avoid no-unreachable false positive after conditional
loop (#22869) (camc314)
- 39d92d6 linter/arrow-body-style: Preserve comments within function
(#22854) (Sysix)
- 3d13e29 parser: Reject `declare` in an already-ambient context
(TS1038) (#22850) (Boshen)
- 5152854 parser: Reject statements in ambient contexts (TS1036)
(#22849) (Boshen)
- 2eafea6 parser: Reject function implementations in ambient contexts
(TS1183) (#22845) (Boshen)
- c645615 parser: Reject incompatible class member modifiers (#22843)
(Boshen)
- 4a1ca4a linter/export: Detect duplicate explicit exports (#22798)
(camc314)
- 0a9a735 linter/no-loop-func: Allow safe let closures (#22811)
(camc314)
- 1599f11 linter: Align lsp extends default plugins (#22788) (camc314)
- db32ec9 linter/no-accumulating-spread: Use loop as primary span
(#22800) (camc314)
- 33ec6b4 linter/consistent-test-it: Avoid adjacent describe leakage
(#22796) (camc314)
- 2606069 linter/no-array-sort: Unwrap parenthesized sort args (#22794)
(camc314)
- 9f2f709 linter/no-array-sort: Skip non compare fn sort arguments
(#22752) (Gaurav Dubey)
- 27268a0 linter/no-else-return: Preserve statement boundary in fixer
(#22687) (camc314)
- d9cb6d8 linter/no-empty-function: Allow functions callbacks with
`allow: functions` (#22764) (camc314)
- a40a314 linter/no-shadow-restricted-names: Ignore enum members
(#22762) (camc314)
- 82366d9 linter/no-cond-assign: Align ternary handling (#22761)
(camc314)

### 📚 Documentation

- 5e113ba linter: Add license notices for ported ESLint plugins (#22768)
(Boshen)
# Oxfmt
### 🚀 Features

- d75cbbf oxfmt: Format `parser:json` files by `oxc_formatter_json`
(#22709) (leaysgur)
- 49db054 formatter_json: Implement `oxc_formatter_json` (json variant
only) (#22641) (leaysgur)
- 9c71f2e ast, codegen, formatter: Add `WithClauseKeyword::as_str`
helper and use it (#22791) (camc314)

### 🐛 Bug Fixes

- d3cdd62 oxfmt: Skip formatting for whitespace-only file (#22780)
(leaysgur)
- 23f0cc8 formatter: Don't move comments inside variable declaration in
for in loop (#22776) (leaysgur)
- f200c40 formatter: Don't move comments inside variable declaration in
for of loop (#22773) (Leonabcd123)

### 📚 Documentation

- 845f393 oxfmt,formatter,formatter_json,formatter_core: Add/update
AGENTS.md (#22873) (leaysgur)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-linter Area - Linter

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants